Chris Williams
Chris Williams

Reputation: 432

D3 disable pan & zoom when scrolling

I've rendered a d3 map that has pan and zoom enabled, but when scrolling down the viewport either on desktop or mobile, the window gets stuck zooming in the map.

Is there a way to temporarily disable d3.zoom, while the window is scrolling?

I've seen ways of toggling the zoom/pan using a button as seen here: http://jsfiddle.net/0xncswrk/, but I wanted to know if it's possible without having to add a button. Here's my current zoom logic.

Thanks!

this.zoom = d3.zoom()
  .scaleExtent([1, 8])
  .on('zoom', () => {
    this.svg.attr('transform', d3.event.transform);
  });

this.svg = d3.select(this.el).append('svg')
    .attr('width', '100%')
    .attr('height', this.height)
    .attr('class', 'bubble-map__svg-us')
    .call(this.zoom)
    .append('g');

Upvotes: 6

Views: 7275

Answers (2)

Lucas van Heerikhuizen
Lucas van Heerikhuizen

Reputation: 105

Got here because I was dealing with a similar problem. Perhaps for anyone coming after this, a simple way to deal with this might be to use the filter() method that a zoom() instance provides. That will allow you to toggle between applying or ignoring zoom events altogether. It works a little better than temporarily setting null to watchers because - at least in my experience - the events then still get recorded and stacked. As a consequence, you would zoom in or out in unexpected leaps once you re-enabled the handler. The filter actually really ignores what's going on, it seems. To implement:

let isZooming = true; // Use controls to set to true or false

zoom()
    // Make sure we only apply zoom events if zooming is enabled by the user
    .filter(() => isZooming)
    .on('zoom', event => {
      // Specify whatever you want to do with the event
    });

Doc: https://github.com/d3/d3-zoom#zoom_filter

Upvotes: 1

aug
aug

Reputation: 11714

EDIT: Wow old answer but never saw your comment. Sorry about that. Yeah sorry I forgot to consider mobile zooming.

In the documentation, perhaps this is new, but they recommend having more granular control of what zoom you allow by using zoom.filter. For touch related events, they also support zoom.touchable.

As specified in the d3-zoom documentation

To disable just wheel-driven zooming (say to not interfere with native scrolling), you can remove the zoom behavior’s wheel event listener after applying the zoom behavior to the selection:

selection .call(zoom) .on("wheel.zoom", null);

You can also consider just setting the scaleExtent to be [1,1] especially if it's just temporary so it locks the zoom to only one possible scale but preferably you opt for what the documentation says :P

Upvotes: 9

Related Questions