{
title: 'Advanced',
children: [
+ 'advanced/data-decimation',
'advanced/progress-bar',
'advanced/radial-gradient',
'advanced/linear-gradient',
| Name | Type | Default | Description
| ---- | ---- | ------- | -----------
-| `enabled` | `boolean` | `true` | Is decimation enabled?
+| `enabled` | `boolean` | `false` | Is decimation enabled?
| `algorithm` | `string` | `'min-max'` | Decimation algorithm to use. See the [more...](#decimation-algorithms)
| `samples` | `number` | | If the `'lttb'` algorithm is used, this is the number of samples in the output dataset. Defaults to the canvas width to pick 1 sample per pixel.
2. The dataset must be a line
3. The X axis for the dataset must be either a `'linear'` or `'time'` type axis
4. The dataset object must be mutable. The plugin stores the original data as `dataset._data` and then defines a new `data` property on the dataset.
+
+## Related Samples
+
+* [Data Decimation Sample](../samples/advanced/data-decimation)
--- /dev/null
+# Data Decimation
+
+This example shows how to use the built-in data decimation to reduce the number of points drawn on the graph for improved performance.
+
+```js chart-editor
+// <block:actions:3>
+const actions = [
+ {
+ name: 'No decimation (default)',
+ handler(chart) {
+ chart.options.plugins.decimation.enabled = false;
+ chart.update();
+ }
+ },
+ {
+ name: 'min-max decimation',
+ handler(chart) {
+ chart.options.plugins.decimation.algorithm = 'min-max';
+ chart.options.plugins.decimation.enabled = true;
+ chart.update();
+ },
+ },
+ {
+ name: 'LTTB decimation (50 samples)',
+ handler(chart) {
+ chart.options.plugins.decimation.algorithm = 'lttb';
+ chart.options.plugins.decimation.enabled = true;
+ chart.options.plugins.decimation.samples = 50;
+ chart.update();
+ }
+ },
+ {
+ name: 'LTTB decimation (500 samples)',
+ handler(chart) {
+ chart.options.plugins.decimation.algorithm = 'lttb';
+ chart.options.plugins.decimation.enabled = true;
+ chart.options.plugins.decimation.samples = 500;
+ chart.update();
+ }
+ }
+];
+// </block:actions>
+
+// <block:data:1>
+const NUM_POINTS = 100000;
+Utils.srand(10);
+
+// parseISODate returns a luxon date object to work with in the samples
+// We will create points every 30s starting from this point in time
+const start = Utils.parseISODate('2021-04-01T00:00:00Z').toMillis();
+const pointData = [];
+
+for (let i = 0; i < NUM_POINTS; ++i) {
+ // Most data will be in the range [0, 20) but some rare data will be in the range [0, 100)
+ const max = Math.random() < 0.001 ? 100 : 20;
+ pointData.push({x: start + (i * 30000), y: Utils.rand(0, max)});
+}
+
+const data = {
+ datasets: [{
+ borderColor: Utils.CHART_COLORS.red,
+ borderWidth: 1,
+ data: pointData,
+ label: 'Large Dataset',
+ radius: 0,
+ }]
+};
+// </block:data>
+
+// <block:decimation:0>
+const decimation = {
+ enabled: false,
+ algorithm: 'min-max',
+};
+// </block:decimation>
+
+// <block:setup:2>
+const config = {
+ type: 'line',
+ data: data,
+ options: {
+ // Turn off animations and data parsing for performance
+ animation: false,
+ parsing: false,
+
+ interaction: {
+ mode: 'nearest',
+ axis: 'x',
+ intersect: false
+ },
+ plugins: {
+ decimation: decimation,
+ },
+ scales: {
+ x: {
+ type: 'time',
+ ticks: {
+ source: 'auto',
+ // Disabled rotation for performance
+ maxRotation: 0,
+ autoSkip: true,
+ }
+ }
+ }
+ }
+};
+// </block:setup>
+
+module.exports = {
+ actions: actions,
+ config: config,
+};
+```
export function newDateString(days) {
return DateTime.now().plus({days}).toISO();
}
+
+export function parseISODate(str) {
+ return DateTime.fromISO(str);
+}
return decimated;
}
+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});
+ }
+ });
+}
+
export default {
id: 'decimation',
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;
}
},
destroy(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});
- }
- });
+ cleanDecimatedData(chart);
}
};