javascriptarrayschart.jsexport-to-csv

Chart.js get array of currently visible points on graph


Using Chart.js with zoom/pan enabled, I am trying to write a function to export only what is visible on the canvas to CSV.

But I cannot figure out how to get only the visible datapoints after the user zooms/pans.

I know I can just look at myChart.data.datasets but that would fetch all the points in the chart, not just the currently visible ones.

var config = {
    type: 'line',
    data: {
        // data is from API call
    }
        pan: {
            enabled: true,
            mode: 'xy'
        },
        zoom: {
            enabled: true,
            mode: 'xy'
        },
        bezierCurve : false
    }
};

var ctx = document.getElementById('myChart').getContext('2d');
window.myChart = new Chart(ctx, config);

$('#exportTheseRunsToCSV').on('click', function() {
    // something like myChart.getVisibleDataPoints() ???
    console.log(chart)
    console.log(chart.data.datasets)
});

There has to be some internal API call to get the visible points, as I also have a function to export the current visible points to PNG and that only grabs what is currently drawn on the canvas:

<a id="exportTheseRuns" class="text-white" href="#" download="image.png" download><i class="fas fa-download"></i> Export to PNG</a>

$('#exportTheseRuns').on('click', function() {
    $('#exportTheseRuns').attr('href', myChart.toBase64Image());
})

The function .toBase64Image() seems like it internally does what I am looking for, as it will only capture visible points, but then it returns a Base64 URI which I can't use for my arrayToCSV function.


Solution

  • The chart object contains minIndex and maxIndex properties that can be used to slice the dataset for the visible values.

    Here's a snippet showing how to use the plugin-provided functions onPanComplete and onZoomComplete to output the visible values after panning or zooming the chart:

    function getVisibleValues({
      chart
    }) {
      let x = chart.scales["x-axis-0"];
    
      document.getElementById("vv").innerText = JSON.stringify(chart.data.datasets[0].data.slice(x.minIndex, x.maxIndex + 1));
    }
    
    new Chart(document.getElementById("chart"), {
      type: "line",
      data: {
        labels: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'],
        datasets: [{
          data: [0, 1, 2, 4, 8, 16, 32, 64, 128, 256]
        }]
      },
      options: {
        maintainAspectRatio: false,
        scales: {
          xAxes: [{
            ticks: {
              min: 'c',
              max: 'h'
            }
          }]
        },
        plugins: {
          zoom: {
            pan: {
              enabled: true,
              mode: 'x',
              onPanComplete: getVisibleValues
            },
            zoom: {
              enabled: true,
              mode: 'x',
              onZoomComplete: getVisibleValues
            }
          }
        }
      }
    });
    <script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.1"></script>
    <script src="https://cdn.jsdelivr.net/npm/hammerjs@2.0.8"></script>
    <script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom@0.7.4"></script>
    <canvas id="chart" style="max-height:125px"></canvas>
    <p>
      Visible values: <span id="vv"></span>
    </p>