Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
easy d3 zoom and pan

I know a lot of people have trouble zooming and panning d3. Indeed, I found myself in a situation where I had a simple bar chart to which I wanted to add the zoom behavior, and also make the full chart draggable. I saw several extremely complex examples of d3 charts with zooming and panning, and thought that there must be an easier way, particularly if you don't need to scale the x and y axes. There is, and here is is in CoffeeScript:

vis.call(d3.behavior.zoom()
  .on("zoom", ->
    g.attr("transform", "translate(" + d3.event.translate[0] + "," + d3.event.translate[1] + ") scale(" + d3.event.scale + ")")
  )
)

And in JavaScript:

vis.call(d3.behavior.zoom()
  .on("zoom", function() {
    g.attr("transform", "translate(" + d3.event.translate[0] + "," + d3.event.translate[1] + ") scale(" + d3.event.scale + ")")
  })
)

In order to implement this in your chart, you simply need to create a svg group g as a child element beneath your main chart svg object, in this case called vis. Then you reference and set the attributes for that group under the on("zoom") method, using the d3.event parameters provided by that method. And you should then have a chart that you can zoom and pan with the mousewheel, as well as drag with the mouse.

If you want more control of the zooming and panning, you can add any of the following methods before the .on method above:

  .translate([0, 0])
  .scale(1.0)
  .scaleExtent([0.5, 8.0])
@guayosr

This comment has been minimized.

Copy link

guayosr commented Aug 6, 2013

Hi!

I'm new to d3 and having a bit of trouble implementing this... could you help me out? This is what I have, but I'm not sure where or how to create the child element.

Thanks!

var force = d3.layout.force()
        .nodes(d3.values(nodes))
        .links(links)
        .size([width, height])
        .linkDistance(1)
        .charge(-60)
        .gravity(.5)
        .on("tick", tick)
        .start();

    var svg = d3.select("body").append("svg");

    var link = svg.selectAll(".link")
        .data(force.links())
      .enter().append("line")
        .attr("class", "link");

    var node = svg.selectAll(".node")
        .data(force.nodes())
      .enter().append("g")
        .attr("class", "node")
        .call(force.drag);

    node.append("circle")
        .attr("r", .3)
        .append("svg:title")
       .text(function(d) { return d.name; });;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.