Correct decimation plugin documentation (#8801)

* Correct decimation plugin documentation

* The default for decimation is `false`.
* Added a sample for data decimation
* Corrected an issue in the decimation plugin when switched from enabled to disabled
This commit is contained in:
Evert Timberg 2021-04-03 13:06:31 -04:00 committed by Jukka Kurkela
parent 9f0f49e87e
commit 2a9ee23a22
5 changed files with 137 additions and 9 deletions

View File

@ -205,6 +205,7 @@ module.exports = {
{ {
title: 'Advanced', title: 'Advanced',
children: [ children: [
'advanced/data-decimation',
'advanced/progress-bar', 'advanced/progress-bar',
'advanced/radial-gradient', 'advanced/radial-gradient',
'advanced/linear-gradient', 'advanced/linear-gradient',

View File

@ -8,7 +8,7 @@ Namespace: `options.plugins.decimation`, the global options for the plugin are d
| Name | Type | Default | Description | 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) | `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. | `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.
@ -35,3 +35,7 @@ To use the decimation plugin, the following requirements must be met:
2. The dataset must be a line 2. The dataset must be a line
3. The X axis for the dataset must be either a `'linear'` or `'time'` type axis 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. 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)

View File

@ -0,0 +1,113 @@
# 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,
};
```

View File

@ -155,3 +155,7 @@ export function newDate(days) {
export function newDateString(days) { export function newDateString(days) {
return DateTime.now().plus({days}).toISO(); return DateTime.now().plus({days}).toISO();
} }
export function parseISODate(str) {
return DateTime.fromISO(str);
}

View File

@ -141,6 +141,17 @@ function minMaxDecimation(data, availableWidth) {
return decimated; 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 { export default {
id: 'decimation', id: 'decimation',
@ -151,6 +162,8 @@ export default {
beforeElementsUpdate: (chart, args, options) => { beforeElementsUpdate: (chart, args, options) => {
if (!options.enabled) { if (!options.enabled) {
// The decimation plugin may have been previously enabled. Need to remove old `dataset._data` handlers
cleanDecimatedData(chart);
return; return;
} }
@ -224,13 +237,6 @@ export default {
}, },
destroy(chart) { destroy(chart) {
chart.data.datasets.forEach((dataset) => { cleanDecimatedData(chart);
if (dataset._decimated) {
const data = dataset._data;
delete dataset._decimated;
delete dataset._data;
Object.defineProperty(dataset, 'data', {value: data});
}
});
} }
}; };