d3.behavior.zoom: programmatic zooming, disable scroll wheel event?

9,490 views
Skip to first unread message

Peter Reinhardt

unread,
Apr 9, 2012, 12:33:26 PM4/9/12
to d3...@googlegroups.com
We've been successfully using d3.behavior.zoom to enable zooming and panning on several different types of plots. So thank you!

However, there doesn't appear to be any way to zoom programmatically. All the zoom actions are driven by scrolling/dragging/clicking interactions. Have you considered exposing a "zoomTo" function? It looks like this doesn't fit well with the structure of d3.behavior.zoom right now... but here are some example use cases: on a map you might want to zoom to Sudan when the user types "Sudan" into some external text box. Or again on a map, if a user double clicks on an SVG element that represents Sudan, you might want to zoom directly to the country. Or, you might want to expose zoom buttons like on Google maps, and have those generate zoom events. Currently we have a monkey patch for this functionality... for example we added a function "d3_behavior_zoomToBoundingBox" that listens for us to programmaticaly fire an event .on("zoomToBoundingBox.zoom", zoomToBoundingBox) and then this generates the appropriate d3.event and dispatches it. Is there a better way to do this? Could programmatic zooming be a new feature in d3.behavior.zoom?

It also appears impossible to block certain interactions from generating events with d3.behavior.zoom. For example, we want to disable scroll wheel actions from causing zooming. Any thoughts on how to improve this?

Thank you,
Peter

Mike Bostock

unread,
Apr 9, 2012, 12:39:37 PM4/9/12
to d3...@googlegroups.com
The behaviors are for interaction. If you want to do things
programmatically, then you probably just want to set a transform
rather than using a behavior. See this series of examples:

http://bl.ocks.org/2206590

Mike

Mike Bostock

unread,
Apr 9, 2012, 12:42:08 PM4/9/12
to d3...@googlegroups.com
Sorry, I should have read more closely; I see you want a mix of
interaction and programmatic control? That should still be possible.
There's another example here where the zoom behavior is constrained
programmatically:

https://github.com/mbostock/d3/blob/master/examples/mercator/mercator-zoom-constrained.html

You can set the zoom behavior's translate and scale properties
externally, but as the above example shows you also want to keep the
derived projection in-sync. (Setting the behavior's translate and
scale does not dispatch zoom events.)

Mike

Peter Reinhardt

unread,
Apr 9, 2012, 12:43:26 PM4/9/12
to d3...@googlegroups.com
Awesome, those examples are great. Thank you for the incredibly fast reply.

Peter Reinhardt

unread,
Apr 9, 2012, 12:59:10 PM4/9/12
to d3...@googlegroups.com
I wish there was an easier way to find all these great examples... you have a ton of really solid ones but they're all buried. Could you list them all somewhere with a search function? Maybe they already are? Google and DDG are terrible at finding them.

Mike Bostock

unread,
Apr 9, 2012, 1:48:11 PM4/9/12
to d3...@googlegroups.com
> I wish there was an easier way to find all these great examples...

Most of the examples are listed on the wiki:

https://github.com/mbostock/d3/wiki

Though, I forgot to list the one I sent you, so it's not perfect.
Also, the list on the wiki isn't that great for finding things because
it doesn't give you a preview or provide much descriptive information
other than a short title.

There's a list of all my gists here:

http://blockses.appspot.com/mbostock

As I have time, I'm trying to write more longer-form examples with
explanation. Those you can find here (and subscribe via RSS or
Twitter):

http://bost.ocks.org/mike/

Mike

Marcus Crowley

unread,
Mar 16, 2014, 9:27:52 PM3/16/14
to d3...@googlegroups.com, mbos...@cs.stanford.edu
Hi Mike,

Can you please send the new link for this as the original link is dead.

Thx

MC

Philip Pedruco

unread,
Mar 19, 2014, 5:40:51 AM3/19/14
to d3...@googlegroups.com, mbos...@cs.stanford.edu
Hi Marcus,

I have a feeling that the example (  https://github.com/mbostock/d3/blob/master/examples/mercator/mercator-zoom-constrained.html) Mike was pointing at was one of the example that were bundled with d3.v2.  You can still get these packages at https://github.com/mbostock/d3/releases?after=v2.10.1 just unpack and find the examples.

Cheers

Mike Bostock

unread,
Mar 19, 2014, 12:02:15 PM3/19/14
to Philip Pedruco, d3...@googlegroups.com
I’m pretty sure I’ve ported all the examples that were previously in the git repository to bl.ocks.org. The Mercator constrained zoom example, for example, is here:


If there’s one you can’t find on http://bl.ocks.org/mbostock then let me know and I’ll figure out where it went.

Mike

Marcus Crowley

unread,
Mar 19, 2014, 10:15:45 PM3/19/14
to d3...@googlegroups.com, Philip Pedruco, mi...@ocks.org
Thanks, guys. The example was unfortunately not quite what I thought it would be.

Following on from Peter's original question, I've uploaded my code so you can have a look at the issue: the mousewheel zoom and click-to-zoom need to play nicely together and there is a gap in my understanding on how to get this sorted. I'd be grateful for any assistance you can provide. Here's the link: http://democra.me/zoom_mc.htm.

(I'll also need to figure out how to cancel the onclick event when panning / dragging, and will need to attend to the stroke-width...)

Best regards

MC

Mike Bostock

unread,
Mar 19, 2014, 11:50:38 PM3/19/14
to Marcus Crowley, d3...@googlegroups.com, Philip Pedruco
Here’s a new example using d3.behavior.zoom’s built-in transition support:


Mike

Marcus Crowley

unread,
Mar 20, 2014, 1:44:49 AM3/20/14
to d3...@googlegroups.com, Marcus Crowley, Philip Pedruco, mi...@ocks.org
Awesome, thanks!

Is there any way to constrain the panning and zooming so that the map doesn't end up clipped when you're zooming back out again. In other words, when scale is 1, it's always centred?

Regards

MC

Elijah Meeks

unread,
Mar 20, 2014, 3:48:59 PM3/20/14
to d3...@googlegroups.com, Marcus Crowley, Philip Pedruco, mi...@ocks.org
Following up on this, there's one example that Peter brought up that's always caused me problems, the generic zoom in and zoom out button that zooms in on the current center of the map. I can't seem to wrap my head around calculating the proper translate for the newly set scale to update zoom.translate(). I just want the zoom in and zoom out to stay centered on the current canvas center, but after digging through translateTo and point and location in the zoom behavior code, I've only muddled myself further away from my starting point.

Thanks,
Elijah

Elijah Meeks

unread,
Mar 20, 2014, 5:01:08 PM3/20/14
to d3...@googlegroups.com, Marcus Crowley, Philip Pedruco, mi...@ocks.org
As usual, the solution is always to post the question and then you realize how simple it is:

function zoomManual(zoomDirection) {
height = parseFloat(document.getElementById("mapSVG").clientHeight);
width = parseFloat(document.getElementById("mapSVG").clientWidth);

  if (zoomDirection == "in") {
var newZoom = zoom.scale() * 1.5;
var newX = ((zoom.translate()[0] - (width / 2)) * 1.5) + width / 2;
var newY = ((zoom.translate()[1] - (height / 2)) * 1.5) + height / 2;
  }
  else {
var newZoom = zoom.scale() * .75;
var newX = ((zoom.translate()[0] - (width / 2)) * .75) + width / 2;
var newY = ((zoom.translate()[1] - (height / 2)) * .75) + height / 2;    
  }

zoom.scale(newZoom).translate([newX,newY])
  zoomed();

Cédric Warny

unread,
Sep 4, 2014, 12:15:08 PM9/4/14
to d3...@googlegroups.com
Thanks so much, Elijah! Your code sample helped me solve a problem I've been stuck on for the last two days!
Reply all
Reply to author
Forward
0 new messages