I`m developing visualization with d3 v6 that's basically use a set of entries to show horizontal layers.
The visualization looks like this:

The caveat is that as number of layers grows some layers become impossible to see due scale decreasing. So I want to make a zoom (and pan) feature, but it has to work only on the Y axis. I've search a lot and found this tutorial (https://observablehq.com/@d3/x-y-zoom) from where I've made some changes to adapt to my visualization:
const svgHeight: any = d3.select(svgContainer.current).attr('height');
const yScaleGlobal = d3
.scaleLinear()
.domain([0, maxYValues])
.range([0, svgHeight - MARGINS.TOP - MARGINS.BOTTOM]);
const yAxis = d3.axisLeft(yScaleGlobal).tickFormat((d: any) => `${d} m`);
const gY = layerGroup.append('g').attr('class', 'y-axis');
// z holds a copy of the previous transform, so we can track its changes
let z = d3.zoomIdentity;
// set up the ancillary zooms and an accessor for their transforms
const zoomY = d3.zoom().scaleExtent([0.2, 5]);
const ty = () => d3.zoomTransform(gY.node());
gY.call(zoomY).attr('pointer-events', 'none');
drawViz();
const zoom = d3.zoom().on('zoom', function (e) {
const t = e.transform;
const k = t.k / z.k;
const point = center(e, this);
if (k === 1) {
// pure translation?
gY.call(zoomY.translateBy, 0, (t.y - z.y) / ty().k);
} else {
// if not, we're zooming on a fixed point
gY.call(zoomY.scaleBy, k, point);
}
z = t;
drawViz();
});
svg.call(zoom).call(zoom.transform, d3.zoomIdentity.scale(0.8)).node();
function drawViz() {
const yr = ty().rescaleY(yScaleGlobal);
yAxis.scale(yr);
gY.call(yAxis, yr);
if (data) updateLayers(data, yr);
}
function center(event, target) {
if (event.sourceEvent) {
const p = d3.pointers(event, target);
return [d3.mean(p, (d) => d[0]), d3.mean(p, (d) => d[1])];
}
return [svgWidth / 2, svgHeight / 2];
}
The updateLayers function is something like this:
const updateLayers = (data: LAYER_COMPONENT_TYPE[], yScale) => {
const layerFill = getLayerFill(data);
const rects = layerGroup.selectAll('rect').data(data);
rects.exit().remove();
const newLayers = rects
.enter()
.append('rect')
.attr('x', 10)
.style('opacity', 0.5)
.attr('width', 300)
.style('stroke', '#101010')
.style('stroke-width', '1px');
newLayers
.merge(rects)
.style('fill', (d: LAYER_COMPONENT_TYPE) => {
if (!layerFill[`${d.fgdc_texture}.${d.from}`].url) {
return layerFill[`${d.fgdc_texture}.${d.from}`];
}
svg.call(layerFill[`${d.fgdc_texture}.${d.from}`]);
return layerFill[`${d.fgdc_texture}.${d.from}`].url();
})
.attr('y', (d: LAYER_COMPONENT_TYPE, i) => {
if (i === 0) return yScale(d.from);
return yScale(data[i - 1].to);
})
.attr('height', (d: LAYER_COMPONENT_TYPE, i) => {
return yScale(d.to - d.from);
});
};
The zoom and pan works fine and the whole visualization too, but the yScale have a strange behavior. The height of the rectangles changes out of scale at zoom or pan (i've realized that the anomaly of the height is equal to the distance of "0 m" point at yScale) here you can view the problem
Anyways, I can figure out what's wrong with the code or what's causing the anomaly. So i want some help with this problem please
Edit 1: I'm using react btw