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
Written by Sébastien Gruhier
Related protips
11 Responses
I added .on("dblclick.zoom", null) just before the .append('g') to disable doubleclick zoom
Oh boy, this is what I call simple, thanks buddy!
How to reset the zoomed graphic to its original scale?
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.
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!
Found the answer, thanks:
zoom.scale(1);
zoom.translate([0, 0]);
svg.transition().duration(500).attr('transform', 'translate(' + zoom.translate() + ') scale(' + zoom.scale() + ')')
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!
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", "mapg")
.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);
});
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.
Thanks!
How do I use this to refer to an external .svg file - e.g. picture.svg?
Have a fresh tip? Share with Coderwall community!
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