D3.js zoom usage

Introduces how to use zoom for mouse and touch events in D3.

Example program

Try dragging or swiping the graph, and using the mouse wheel or pinch-in gesture. Click the reset button below to return to the initial position.

View code

Example code

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>D3 v5 zoom</title>
  <script src="https://d3js.org/d3.v7.min.js"></script>
</head>

<body>

  <script>
    var width = 800;
    var height = 600; // Graph height

    var svg = d3.select("body").append("svg").attr("width", width).attr("height", height);

    var dataset = [];
    for (var i = 0; i < 300; i++) {
      var r = 0.5 * d3.min([height, width]) * Math.random();
      var t = 2 * Math.PI * Math.random();
      dataset.push({
        "x": width / 2 + r * Math.cos(t),
        "y": height / 2 + r * Math.sin(t)
      });
    }

    // Axis settings
    var x = d3.scaleLinear().domain([0, width]).range([0, width]);
    var y = d3.scaleLinear().domain([0, height]).range([0, height]);

    var xAxis = d3.axisBottom(x)
      .ticks(width / height * 10) //
      .tickSize(height)
      .tickPadding(8 - height);

    var yAxis = d3.axisRight(y)
      .ticks(10)
      .tickSize(width)
      .tickPadding(8 - width);

    var gX = svg.append("g").call(xAxis);
    var gY = svg.append("g").call(yAxis);

    var view = svg.selectAll("circle")
      .data(dataset)
      .enter()
      .append("circle")
      .attr("class", "view")
      .attr("cx", function (d) { return d.x })
      .attr("cy", function (d) { return d.y })
      .attr("r", 5)
      .attr("fill", "steelblue")
      .attr("stroke", "black");

    d3.select("#resetButton")
      .on("click", resetted);

    var zoom = d3.zoom()
      .scaleExtent([1, 40])
      .translateExtent([
        [-100, -100],
        [width + 90, height + 100]
      ])
      .on("zoom", zoomed);

    svg.call(zoom);

    function zoomed(event) {
      view.attr("transform", event.transform);
      gX.call(xAxis.scale(event.transform.rescaleX(x)));
      gY.call(yAxis.scale(event.transform.rescaleY(y)));
    }

    function resetted() {
      svg.transition()
        .duration(750)
        .call(zoom.transform, d3.zoomIdentity);
    }
  </script>
  <div>
    <button id='resetButton'>reset</button>
  </div>

</body>

</html>

Code explanation

When configuring zoom, first call the prototype for the zoom event with d3.zoom(), and then use the call method to set the SVG element where the zoom event is registered. This example sets an SVG element, but you can register it on any element selected with d3.select or d3.selectAll.

var zoom = d3.zoom()
  .scaleExtent([1, 40])
  .translateExtent([
    [-100, -100],
    [width + 90, height + 100]
  ])
  .on("zoom", zoomed);

svg.call(zoom);

d3.zoom() provides the following functions.

Function Description
zoom.scaleExtent() Sets the minimum and maximum scale values.
Set it as an array of two values such as [k0, k1].
The default value is [0, infinity].
zoom.translateExtent() Sets the movable range.
Set it as a two-dimensional array such as [[x0, y0], [x1, y1]].
x0 and y0 are the upper-left coordinates, and x1 and y1 are the lower-right coordinates.
The default value is [[-infinity, -infinity], [+infinity, +infinity]].
zoom.on(typenames, listener) Registers an event. typenames can be one of the following three types:
  • start - when zoom starts
  • zoom - during zoom
  • end - when zoom ends
Register the function to call during the event in listener. If listener is set to null, the registered event is removed.

The on function registers an event listener, which is a function called when the event occurs.

  function zoomed() {
    view.attr("transform", d3.event.transform);
    gX.call(xAxis.scale(d3.event.transform.rescaleX(x)));
    gY.call(yAxis.scale(d3.event.transform.rescaleY(y)));
  }

When the zoom event listener is called, d3.event is set to the current zoom event and the following fields are set.

Method Description
d3.event.target The related D3 zoom behavior is set.
d3.event.type One of start, zoom, or end is set.
d3.event.transform The current zoom scale and translation are set.
d3.event.sourceEvent The original input event, such as mousemove or touchmove, is set.

The event listener is configured using d3.event.transform. If d3.event.transform is assigned to the transform attribute of an SVG element with the attr function, it is transformed at the current scale. The scale can be changed with the following functions set on transform.

Method Description
transform.rescaleX(scale) Changes the domain range of the input scale to match the current zoom value in the x direction.
transform.rescaleY(scale) Changes the domain range of the input scale to match the current zoom value in the y direction.

Finally, set a function that returns to the original position and scale when the reset button is pressed. d3.zoomIdentity has a transform property with scale 0 and translation 0 registered.

svg.call(zoom.transform, d3.zoomIdentity);

If you call it with the call method as above and set it as the current transform value, you can return to the initial state.

Summary

It supports not only mouse operations but also touch events, pinch in, and pinch out.