I finally almost got it working! The X and Y axes on my scatter plot each have a separate d3.drag()
behavior that adjusts the scale and the plot itself calls d3.zoom()
for panning/zooming. I can pan perfectly but the zooming still isn’t right.
See here: codepen
Typically, zooming is done by setting the scale’s domain to a rescaled version of some default x and y scales (x2, y2) domains that are set initially.
x.domain(d3.event.transform.rescaleX(x2).domain());
y.domain(d3.event.transform.rescaleY(y2).domain());
This works fine by itself but in combination with other zoom and drag behaviors the rescaling causes the zoom state of the plot to be out of sync which makes the plot jump around when panning or zooming.
To circumvent this, each zoom/drag instance directly modifies the scales domains. Everything works well however zooming in and zooming out doesn’t set the domains correctly. I believe I need to implement the d3.event.transform.k
value into calculating the delta somehow. Zooming is possible but it then goes wrong.
// ZOOMING
if (d3.event.sourceEvent && d3.event.sourceEvent.type == "wheel") {
let domainX = x.domain();
let linearX = d3.scaleLinear().domain(x.range()).range([0, domainX[0] - domainX[1]]);
let deltaX = linearX(t.x - lastX);
let domainY = y.domain();
let linearY = d3.scaleLinear().domain(y.range()).range([domainY[1] - domainY[0], 0]);
let deltaY = linearY(t.y - lastY)
if (t.k > lastK) {
// ZOOM IN
x.domain([domainX[0] - deltaX, domainX[1] + deltaX]);
y.domain([domainY[0] + deltaY, domainY[1] - deltaY]);
} else {
// ZOOM OUT
x.domain([domainX[0] + deltaX, domainX[1] - deltaX]);
y.domain([domainY[0] - deltaY, domainY[1] + deltaY]);
}
}
Please help! Thank you.
D3fc is used here but it’s not important.