Repository: chartjs/Chart.js
File: src/plugins/plugin.decimation.js (JavaScript)

Code before:

function cleanDecimatedData(chart) {
  chart.data.datasets.forEach((dataset) => {
    if (dataset._decimated) {
      const data = dataset._data;
      delete dataset._decimated;
      delete dataset._data;
      Object.defineProperty(dataset, 'data', {value: data});
    }
  });
}

function getStartAndCountOfVisiblePointsSimplified(meta, points, animationsDisabled) {
  const pointCount = points.length;

  let start = 0;
  let count;

  const {iScale} = meta;
  const axis = iScale.axis;
  const {min, max, minDefined, maxDefined} = iScale.getUserBounds();

  if (minDefined) {
    start = _limitValue(Math.min(
      _lookupByKey(points, iScale.axis, min).lo,
      animationsDisabled ? pointCount : _lookupByKey(points, axis, iScale.getPixelForValue(min)).lo), 0, pointCount - 1);
  }
  if (maxDefined) {
    count = _limitValue(Math.max(
      _lookupByKey(points, iScale.axis, max).hi + 1,
      animationsDisabled ? 0 : _lookupByKey(points, axis, iScale.getPixelForValue(max)).hi + 1), start, pointCount) - start;
  } else {
    count = pointCount - start;
  }

  return {start, count};
}

export default {
  id: 'decimation',

  defaults: {
    algorithm: 'min-max',
    enabled: false,
  },

  beforeElementsUpdate: (chart, args, options) => {
    if (!options.enabled) {
      // The decimation plugin may have been previously enabled. Need to remove old `dataset._data` handlers
      cleanDecimatedData(chart);
      return;

Review comment (suggestion):
I think this can be simplified to just:
`start = _limitValue(_lookupByKey(points, iScale.axis, min).lo, 0, pointCount -1);`

The other part hast to do with pixels that we don't really know here yet (also its comparing pixel value to data value, which will not work as expected)

Same for max

Code after:
  const pointCount = points.length;

  let start = 0;
  let count;

  const {iScale} = meta;
  const {min, max, minDefined, maxDefined} = iScale.getUserBounds();

  if (minDefined) {
    start = _limitValue(_lookupByKey(points, iScale.axis, min).lo, 0, pointCount - 1);
  }
  if (maxDefined) {
    count = _limitValue(_lookupByKey(points, iScale.axis, max).hi + 1, start, pointCount) - start;
  } else {
    count = pointCount - start;
  }

  return {start, count};
}

export default {
  id: 'decimation',

  defaults: {
    algorithm: 'min-max',
    enabled: false,
  },

  beforeElementsUpdate: (chart, args, options) => {
    if (!options.enabled) {
      // The decimation plugin may have been previously enabled. Need to remove old `dataset._data` handlers
      cleanDecimatedData(chart);
      return;
    }

    // Assume the entire chart is available to show a few more points than needed
    const availableWidth = chart.width;

    chart.data.datasets.forEach((dataset, datasetIndex) => {
      const {_data, indexAxis} = dataset;
      const meta = chart.getDatasetMeta(datasetIndex);
      const data = _data || dataset.data;

      if (resolve([indexAxis, chart.options.indexAxis]) === 'y') {
        // Decimation is only supported for lines that have an X indexAxis
        return;
      }

      if (meta.type !== 'line') {
        // Only line datasets are supported
        return;