Reputation: 2687
This question looks quite similar to this one, but I am still not able to figure out whether it is possible to use d3.behavior.zoom but without the pan ability. In other words I just want to zoom-in/out using the wheel only.
The reason for this is that I want to be able to brush on the "zoomable" area.
Thanks!
Upvotes: 30
Views: 16725
Reputation: 2916
Say you've defined a zoom behavior:
var zoom = d3.behavior.zoom().on('zoom', update);
When you apply the zoom behavior to a selection, you can unregister the event listeners that it uses internally to detect and respond to certain interactions. In your case, you'd want to do something like this:
selection.call(zoom)
.on("mousedown.zoom", null)
.on("touchstart.zoom", null)
.on("touchmove.zoom", null)
.on("touchend.zoom", null);
I'm not sure you want to remove the touch events. Doing so might eliminate double tap zooming. You should experiment with those.
Upvotes: 48
Reputation: 1337
One solution that I found was to stick a rect element in front of the zoom-enabled element (they must be siblings) and set its fill to 'transparent', when I wanted to disable zoom interaction or to 'none', when I wanted to enable zoom interaction. It looked something like this:
if (chart._disableZoom) {
var rootPanel = d3.select('.rootPanel'); // this is the parent of the element that can be zoomed and panned
if (!rootPanel.select('.stopEventPanel').node()) { // create panel if it doesn't exist yet
//.stopEventPanel is appended next to the zoom-enabled element
rootPanel.append('rect').attr('class', 'stopEventPanel').attr('width', renderConfig.width).attr('height', renderConfig.height).attr('fill', 'transparent');
} else { // disable zoom and pan
rootPanel.select('.stopEventPanel').attr('fill', 'transparent');
}
} else { // enable zoom and pan
d3.select('.rootPanel').select('.stopEventPanel').attr('fill', 'none');
}
Upvotes: 1
Reputation: 2687
I guess it would be good sharing the workaround I found to deal with this problem. What I did is to use the listener on the start of the brush to "deactivate" the zoom:
zoom.on("zoom",null);
selection.call(zoom);
and activate it again on the brushend event.
There is one more trick to take into account and comes from the fact that it is important to save the scale and transition values of the last valid zoom interaction, so that you use those values when activating the brush on the brushend event like this
zoom.scale(lastEventScale).translate(lastEventTranslate).on("zoom",drawZoom);
selection.call(scatterZoom);
I would love hearing other more "elegant" solutions to this problem.
Upvotes: 4