Last Updated: August 30, 2022
·
112.1K
· sgruhier

Simplest way to add zoom/pan on d3.js (version 3 and 4)

I needed to add zoom/pan on d3.js visualisation. After a painful search on Google, I finally found a simple way to do it.

d3.js has everything to do it with only a few lines of code.

You just need to create a g element as first child of the SVG element and connect d3.behavior.zoom() behavior.

var svg = d3.select("body")
  .append("svg")
  .attr("width", "100%")
  .attr("height", "100%")
  .call(d3.behavior.zoom().on("zoom", function () {
    svg.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")")
  }))
  .append("g")

That's it!

Now you can add all SVG node to that g view port element.

There is a live example here: http://bl.ocks.org/sgruhier/1d692762f8328a2c9957

Update for v4

For d3v4 it's even simpler, no more d3.behavior.zoom() behavior.

var svg = d3.select("body")
 .append("svg")
 .attr("width", "100%")
 .attr("height", "100%")
 .call(d3.zoom().on("zoom", function () {
    svg.attr("transform", d3.event.transform)
 }))
 .append("g")

There is a live example here https://bl.ocks.org/sgruhier/50990c01fe5b6993e82b8994951e23d0

11 Responses
Add your response

I added .on("dblclick.zoom", null) just before the .append('g') to disable doubleclick zoom

over 1 year ago ·

Oh boy, this is what I call simple, thanks buddy!

over 1 year ago ·

How to reset the zoomed graphic to its original scale?

over 1 year ago ·

you can do
svg.attr("transform", "translate(0,0) scale(1)");
But you'll also need to reset the d3.behavior.zoom. You need to modify a little the snippet to use a variable for the behaviour.
Let me know if it's clear enough. If not, I'll try to get 5 mn to make a new snippet.

over 1 year ago ·

This is awesome! Works like a charm. Is there any chance you can elaborate a bit more on how to do reset the d3.behavior.zoom for a reset button? Thanks!

over 1 year ago ·

Found the answer, thanks:

zoom.scale(1);
zoom.translate([0, 0]);
svg.transition().duration(500).attr('transform', 'translate(' + zoom.translate() + ') scale(' + zoom.scale() + ')')

over 1 year ago ·

Does anyone know how this would be written in v4? I know d3.behavior.zoom becomes d3.zoom but ' .attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")") ' is giving me trouble. Thanks!

over 1 year ago ·

Figured it out. Here's my code that works in D3 V4:

//Width and height
var w = 400,
h = 300;

// projection
var projection = d3.geoAlbersUsa()
.translate([w / 2, h / 2])
.scale([500]);

//Define default path generator
var path = d3.geoPath()
.projection(projection);

// Define Zoom Function Event Listener
function zoomFunction() {
var transform = d3.zoomTransform(this);
d3.select("#map_g")
.attr("transform", "translate(" + transform.x + "," + transform.y + ") scale(" + transform.k + ")");
}

// Define Zoom Behavior
var zoom = d3.zoom()
.scaleExtent([0.2, 10])
.on("zoom", zoomFunction);

//Create SVG element
var svg = d3.select("#main")
.append("svg")
.attr("width", w)
.attr("height", h)
.attr("id", "mapsvg")
.append("g")
.attr("id", "map
g")
.call(zoom);

//Load in GeoJSON data
d3.json("json/us-states.json", function(json) {

//Bind data and create one path per GeoJSON feature
svg.selectAll("path")
   .data(json.features)
   .enter()
   .append("path")
   .attr("d", path);

});

over 1 year ago ·

Thanks! Been scouring the web for a quick and easy solution (I'm a total noob with d3), but it was your post that helped me.

over 1 year ago ·

Thanks!

over 1 year ago ·

How do I use this to refer to an external .svg file - e.g. picture.svg?

over 1 year ago ·

Have a fresh tip? Share with Coderwall community!

Post
Post a tip
Did you know?

JavaScript on a page runs with the privileges of that origin. One altered library, tag manager, or snippet can read inputs, change what people see, and call your APIs as the user.

Security insights from Cside