I have a chart with two y-axes. They have their separate ranges and domains, and the tickvalues are updated to make sense visually.
The problems starts on zoom. How can I adapt the zoom functionality to update the two scales synchronously – meaning that they should always maintain an equal number of tick values, the tick values needs keep their “rounding” (a stepsize below one only shows .10, .20, .30 etc (not .33, .44 etc) and a higher stepsize is rounded down to x10, x20, x30 etc), and the tick labels need to align.
Am I wanting the impossible?
const onZoom = ({ transform }) => {
let y1Scaled = transform.rescaleY(y1Scale);
let y2Scaled = transform.rescaleY(y2Scale);
let x1Scaled = transform.rescaleX(xScale);
let zoomStepsY1 = y1Steps / 5;
let zoomStepsY2 = y2Steps / 5;
const y2TickValues =
y2Steps > 1 ?
d3.range(
(Math.floor(y2Scaled.domain()[0] / y2Steps / 5) * y2Steps) / 5,
(Math.ceil(y2Scaled.domain()[1] / y2Steps / 5) * y2Steps) / 5 +
y2Scaled.domain()[1],
zoomStepsY2,
) :
d3.range(
Math.floor(y2Scaled.domain()[0]),
Math.ceil(y2Scaled.domain()[1]) + y2Scaled.domain()[1],
zoomStepsY2,
);
gX1.call(xAxis.scale(x1Scaled));
gY1.call(
y1Axis
.scale(y1Scaled)
.tickValues(
d3.range(
Math.floor(y1Scaled.domain()[0]),
Math.ceil(y1Scaled.domain()[1]) + y1Scaled.domain()[1],
zoomStepsY1,
),
),
);
gY2.call(y2Axis.scale(y2Scaled).tickValues(y2TickValues));
svg
.select(".firstLine")
.select("path")
.attr(
"d",
line.x((d) => x1Scaled(d.x) - x1Scaled(0)).y((d) => y1Scaled(d.y1)),
);
svg
.select(".secondLine")
.select("path")
.attr(
"d",
line.x((d) => x1Scaled(d.x) - x1Scaled(0)).y((d) => y2Scaled(d.y2)),
);
};
Here’s a fiddle: https://jsfiddle.net/evebeam/o2p8wuz9/50/
I get it to work but only for one step level. I am expecting it to continuously scale to finer (rounded) numbers.