d3 / d3-zoom

Pan and zoom SVG, HTML or Canvas using mouse or touch input.
https://d3js.org/d3-zoom
ISC License
502 stars 143 forks source link

Only last Y-axis is being updated while dragging on d3 chart #197

Closed diamond122 closed 4 years ago

diamond122 commented 4 years ago

Hello, Friends. My chart has multiple Y-Axes that have different domains. When I am dragging on the chart, unfortunately only the last y-axis is being updated. Peek 2019-11-15 07-08 I added each y-axis like below;

addYAxis(data, tag) { // tag is for index of each y-axis. e.g: 0, 1, 2
  const yScale = d3.scale.linear()
    .domain([0, this.innerHeight])
    .range([this.innerHeight, 0]);
  const yAxis = d3.svg.axis()
    .scale(yScale)
    .orient(tag ? 'right' : 'left')
    .tickSize(tag ? this.innerWidth + 50 * (tag - 1) : -this.innerWidth);
  const yAxisElement = this.g.append('g')
    .attr('class', 'y axis')
    .call(yAxis);
  this.yAxisList.push({yScale, yAxis, yAxisElement});
}

Here is the zoom list for each axis.

this.zoom.push(d3.behavior.zoom()
    .x(this.xScale)
    .y(this.yAxisList[tag].yScale)  // when I replace [tag] with [0], then only first axis is being updated.
    .scaleExtent([.5, 10])
    .scale(this.currentZoom)
    .translate(this.currentPan)
    .on('zoom', () => this.zoomed(tag))
    .on('zoomend', () => {
        setTimeout(() => { this.zooming = false; }, 10);
    }));

this.g.call(this.zoom[tag])  // when I replace [tag] with [0], then only first axis is being updated.
    .on('dblclick.zoom', null);

And update them like below;

updateYAxis() {
  this.yAxisList.forEach(({yAxisElement, yAxis}) => yAxisElement.call(yAxis));
}

Structure of this chart: image

How to update all Y-axes while dragging on the chart? Thanks in advance.

diamond122 commented 4 years ago

I found the solution to update all y-axes when dragging. When one of the zoom objects is updated, I need to update scale and translate for other zoom objects.

this.zoom.push(d3.behavior.zoom()
    .x(this.xScale)
    .y(this.yAxisList[tag].yScale)  // when I replace [tag] with [0], then only first axis is being updated.
    .scaleExtent([.5, 10])
    .scale(this.currentZoom)
    .translate(this.currentPan)
    .on('zoom', () => {
        // update other zoom object - COOL! ;)
         this.zoom.forEach((zoom, t) => {
            zoom.scale(this.zoom[tag].scale());
            zoom.translate(this.zoom[tag].translate());
        this.zoomed(t);
         });
    })
    .on('zoomend', () => {
        setTimeout(() => { this.zooming = false; }, 10);
    }));