Chart.js How to synchronize pan and zoom in multiple chats
Asked Answered
T

2

6

I want to synchronize pan and zoom on multiple charts. I'm been using Chart.js with chartjs-plugin-zoom.

charjs-plugin-zoom calls an event with the onZoom callback function. So, the values ​​at both ends of the X axis are obtained in this way with the callback function.

onZoom: function () {
    var minVal = myChartA.getDatasetMeta(0).dataset._scale.chart.scales['x-axis-0']._table[0].time;
    var maxVal = myChartA.getDatasetMeta(0).dataset._scale.chart.scales['x-axis-0']._table[1].time;

    leftEnd = minVal;
    rightEnd = maxVal;

    updateChart();
}

Then update the chart with the updateChart function.

I thought that other charts should be updated with the values ​​of both ends of the X axis obtained by the updateChart function. Call update () with Chart.helpers.each to update all charts.

function updateChart() {
    Chart.helpers.each(Chart.instances, function (instance) {
        instance.oprions = {
            scales: [{
                xAxes: {
                    time: {
                        min: leftEnd,
                        max: rightEnd
                    }
                }
            }]
        };
        instance.update();
    });
}

However, the expected result was not obtained. Zoom-PAN reflected only the chart that was operated.

I think that onZoom callback function gets both edge of X-Axis, and updates chart every frame. Charts can only be updated with options, so Chart.helpers.each can be used to update all charts at once. If both ends of the X axis to be updated are global variables, all graphs can be referenced.

Is this method incorrect? Is the option update method wrong? Is the update timing wrong?


UPDATE

I found out how to update the chart by referring to https://www.chartjs.org/docs/latest/developers/updates.html.

Actually, X-axis scales rage of multiple charts has changed, but max zoomed and stopped working again.

Reason is not to update reference. What is ? The sample code is written as "need to update the reference" as comment. What's mean?

Sample code calles below:

xScale = chart.scales['newId'];

"newId" is re-assigned as scales id.

But mine is min and max value of scale. How??

JSFillde

Tourist answered 1/11, 2019 at 2:37 Comment(0)
T
10

I figured out how to do this. It’s not a big deal if I know.

Callback function updateChart() should be like this:

        function updateChart() {
            Chart.helpers.each(Chart.instances, function (instance) {
                instance.options.scales.xAxes[0].time.min = leftEnd;
                instance.options.scales.xAxes[0].time.max = rightEnd;              
                instance.update();
            });
        }

Point is that my data is time series data so that scale option should be use "time".

JSFillde is updated.

Tourist answered 1/11, 2019 at 14:33 Comment(3)
Nice, but how about chart.js v3.2.1? Seems that there were some incompatible changes since last JSFiddle was attached.Byington
Found out that linear chart (v3.2.1) will work if you change code from ".xAxes[0].time.max" to ".x.max"Byington
If you also use resetZoom() to reset your zoom, it won't work anymore. You'll have to use instance.options.scales.x.min = null; instance.options.scales.x.max = null; instance.update();Geriatric
O
0

I found a solution that worked great with chart.js V4 - if anyone has issues with this.

zoom: {
    pan: {
      onPan({ chart }) {
        secChartRef.current.zoomScale(
          'x',
          { min: Math.trunc(chart.scales.x.min), max: Math.trunc(chart.scales.x.max) },
          'none'
        );
      },
      enabled: true,
      mode: 'x'
    },
    limits: {
      x: { min: 'original', max: 'original' }
    },
    zoom: {
      mode: 'x',
      onZoom({ chart }) {
        secChartRef.current.zoomScale(
          'x',
          { min: Math.trunc(chart.scales.x.min), max: Math.trunc(chart.scales.x.max) },
          'none'
        );
      },
      drag: {
        enabled: false
      },
      pinch: {
        enabled: true
      },
      wheel: {
        enabled: true
      }
    }
  }

Then do the same but with the ref for the first chart on the options for the secondary chart.

Offenseless answered 8/5 at 9:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.