block by mbostock a980aba1197350ff2d5a5d0f5244d8d1

Pan & Zoom V

Full Screen

This example demonstrates how to fixate d3-zoom on a point of interest: zooming using the wheel or touch is allowed, but panning is not. When a zoom event is emitted, the current transform is translated to put the focus point at the center of the viewport:

var point = transform.invert(center);
transform = transform.translate(point[0] - focus[0], point[1] - focus[1]);

Compare this to non-fixated zooming.

index.html

<!DOCTYPE html>
<meta charset="utf-8">
<canvas width="960" height="500"></canvas>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>

var canvas = d3.select("canvas"),
    context = canvas.node().getContext("2d"),
    width = canvas.property("width"),
    height = canvas.property("height"),
    radius = 2.5;

var points = d3.range(2000).map(phyllotaxis(10)),
    center = [width / 2, height / 2],
    focus = points[0];

canvas.call(zoom = d3.zoom()
    .scaleExtent([1 / 2, 64])
    .on("zoom", zoomed));

drawPoints();

function zoomed() {
  var transform = d3.event.transform,
      point = transform.invert(center);
  transform = transform.translate(point[0] - focus[0], point[1] - focus[1]);
  context.save();
  context.clearRect(0, 0, width, height);
  context.translate(transform.x, transform.y);
  context.scale(transform.k, transform.k);
  drawPoints();
  context.restore();
}

function drawPoints() {
  context.beginPath();
  points.forEach(drawPoint);
  context.fill();
}

function drawPoint(point) {
  context.moveTo(point[0] + radius, point[1]);
  context.arc(point[0], point[1], radius, 0, 2 * Math.PI);
}

function phyllotaxis(radius) {
  var theta = Math.PI * (3 - Math.sqrt(5));
  return function(i) {
    var r = radius * Math.sqrt(i), a = theta * i;
    return [
      width / 2 + r * Math.cos(a),
      height / 2 + r * Math.sin(a)
    ];
  };
}

</script>