Smooth zooming
This notebook demonstrates using d3.interpolateZoom to implement smooth pan-and-zoom transitions between two views. See also d3.zoom’s transitions, which also allows freeform zooming.
const theta = Math.PI * (3 - Math.sqrt(5));
const height = 500;
const radius = 6;
const step = radius * 2;
const data = Array.from({length: 2000}, (_, i) => {
const r = step * Math.sqrt(i += 0.5), a = theta * i;
return [
width / 2 + r * Math.cos(a),
height / 2 + r * Math.sin(a)
];
});
let currentTransform = [width / 2, height / 2, height];
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height);
const g = svg.append("g");
g.selectAll("circle")
.data(data)
.join("circle")
.attr("cx", ([x]) => x)
.attr("cy", ([, y]) => y)
.attr("r", radius)
.attr("fill", (d, i) => d3.interpolateRainbow(i / 360))
function transition() {
const d = data[Math.floor(Math.random() * data.length)];
const i = d3.interpolateZoom(currentTransform, [...d, radius * 2 + 1]);
g.transition()
.delay(250)
.duration(i.duration)
.attrTween("transform", () => (t) => transform(currentTransform = i(t)))
.on("end", transition);
}
function transform([x, y, r]) {
return `
translate(${width / 2}, ${height / 2})
scale(${height / r})
translate(${-x}, ${-y})
`;
}
display(svg.call(transition).node());