New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add flag to zoom behavior to control zooming origin. #616

Closed
wants to merge 1 commit into
base: master
from

Conversation

2 participants
@marcneuwirth

marcneuwirth commented Apr 16, 2012

This allows users to easily disable the event handlers that they don't want, or separate the handling of zoom events into different functions like:

var zoomTranslate = d3.behavior.zoom({
        dblclick: false,
        wheel: false
    })
    .translate(projection.origin())
    .on("zoom", translate);

var zoomScale = d3.behavior.zoom({
        click: false,
        dblclick: false,
        touch: false
    })
    .scale(projection.scale())
    .scaleExtent([100, 800])
    .on("zoom", scale);

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
    .call(zoomTranslate)
    .call(zoomScale)

This is very useful if you only want the scroll wheel to scale and not translate as well.

@mbostock

This comment has been minimized.

Show comment
Hide comment
@mbostock

mbostock Apr 16, 2012

Member

What about unregistering the events after applying the zoom behavior? For example, you can disable touch and double-click events like so:

var zoom = d3.behavior.zoom()
    .translate(projection.translate())
    .scale(projection.scale())
    .scaleExtent([100, 800])
    .on("zoom", zoommove);

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
    .call(zoom)
    .on("dblclick.zoom", null)
    .on("touchstart.zoom", null);
Member

mbostock commented Apr 16, 2012

What about unregistering the events after applying the zoom behavior? For example, you can disable touch and double-click events like so:

var zoom = d3.behavior.zoom()
    .translate(projection.translate())
    .scale(projection.scale())
    .scaleExtent([100, 800])
    .on("zoom", zoommove);

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
    .call(zoom)
    .on("dblclick.zoom", null)
    .on("touchstart.zoom", null);
@marcneuwirth

This comment has been minimized.

Show comment
Hide comment
@marcneuwirth

marcneuwirth Apr 17, 2012

That will work for cases where you just want to just disable the handler, but not separate handling of the events to different functions.

The real problem is in the way scale is coupled with translate in the mousewheel function. This works fantastically in the basic use case, but makes it impossible to decouple them if you want to zoom straight ahead instead of to the mouse. This is also problem if you want to use zoom on a azimuthal projection, where you want to change the origin and not translate.

Maybe there is a better way to prevent mousewheel from changing translate when necessary

marcneuwirth commented Apr 17, 2012

That will work for cases where you just want to just disable the handler, but not separate handling of the events to different functions.

The real problem is in the way scale is coupled with translate in the mousewheel function. This works fantastically in the basic use case, but makes it impossible to decouple them if you want to zoom straight ahead instead of to the mouse. This is also problem if you want to use zoom on a azimuthal projection, where you want to change the origin and not translate.

Maybe there is a better way to prevent mousewheel from changing translate when necessary

@mbostock

This comment has been minimized.

Show comment
Hide comment
@mbostock

mbostock Apr 17, 2012

Member

It's a bit of a hack, but another option is to have two zoom behaviors on nested elements:

<g class="scale">
  <g class="translate">
  </g>
</g>

Then you bind an inner zoom behavior and an outer zoom behavior, and delete the event listeners as needed. The stop propagation should allow you to use both zoom behaviors independently.

But really I think the simpler solution here is to add a flag to the zoom behavior that says whether mousewheel zooming should zoom on the origin or zoom on the mouse location. I'd support that change. In fact, I implemented exactly that feature for Polymaps; see Wheel.js.

Member

mbostock commented Apr 17, 2012

It's a bit of a hack, but another option is to have two zoom behaviors on nested elements:

<g class="scale">
  <g class="translate">
  </g>
</g>

Then you bind an inner zoom behavior and an outer zoom behavior, and delete the event listeners as needed. The stop propagation should allow you to use both zoom behaviors independently.

But really I think the simpler solution here is to add a flag to the zoom behavior that says whether mousewheel zooming should zoom on the origin or zoom on the mouse location. I'd support that change. In fact, I implemented exactly that feature for Polymaps; see Wheel.js.

@marcneuwirth

This comment has been minimized.

Show comment
Hide comment
@marcneuwirth

marcneuwirth Apr 17, 2012

I agree, that seems like a much better solution

marcneuwirth commented Apr 17, 2012

I agree, that seems like a much better solution

mbostock added a commit that referenced this pull request Jun 30, 2013

@mbostock

This comment has been minimized.

Show comment
Hide comment
@mbostock

mbostock Jun 30, 2013

Member

Superseded by #1352.

Member

mbostock commented Jun 30, 2013

Superseded by #1352.

@mbostock mbostock closed this Jun 30, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment