Tyler Graf Tyler Graf - 8 days ago 5
Javascript Question

d3 pan/zoom with DOM center point is off

I'm trying to zoom and pan using d3.

I took an example from here and switched out the svg for regular dom.

Code:

var section = d3.select("section"),
width = +section.attr("width"),
height = +section.attr("height");

var points = d3.range(2000).map(phyllotaxis(10));

var div = section.append("div");

div.selectAll("p")
.data(points)
.enter().append("p")
.attr("style", function(d) { return 'left: '+d[0]+'px; top: '+d[1]+'px;' })
.text('hi');

section.call(d3.zoom()
.scaleExtent([1 / 2, 4])
.on("zoom", zoomed));

function zoomed() {
div.attr("style", `transform: translate(${d3.event.transform.x}px, ${d3.event.transform.y}px) scale(${d3.event.transform.k})`);
div.attr("transform", d3.event.transform);
}

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


Here's a codepen showing the issue.

Issue:
Notice that pan works great, but the zoom center point is off. It should zoom in centered on wherever your mouse is.

Answer

Assuming you really needed that <div>s and <p>s instead of <g>s and <circle>s;

Your translate coefficients are a bit off.

Changing your

function zoomed() {
  g.attr("style", `transform: translate(${d3.event.transform.x}px, ${d3.event.transform.y}px) scale(${d3.event.transform.k})`);
  g.attr("transform", d3.event.transform);
}

to

function zoomed() {
  g.attr("style", `transform: translate(${d3.event.transform.x-480}px, ${d3.event.transform.y}px) scale(${d3.event.transform.k})`);
  g.attr("transform", d3.event.transform);
}

will "solve" your issue I think.

Here's the updated codepen: http://codepen.io/anon/pen/bBoPVx