Skip to content

Instantly share code, notes, and snippets.

@mbostock
Last active July 4, 2016 13:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mbostock/a980aba1197350ff2d5a5d0f5244d8d1 to your computer and use it in GitHub Desktop.
Save mbostock/a980aba1197350ff2d5a5d0f5244d8d1 to your computer and use it in GitHub Desktop.
Pan & Zoom V
license: gpl-3.0

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.

<!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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment