Docs › Interaction and export
Large data (downsampling, progressive)
Tens of thousands of points: LTTB thinning, progressive painting, a light hidden table and fast hover; CSV keeps everything.
When a line or area chart has more than 2,000 points, 82chart draws about one point per pixel of plot width. It picks them with LTTB (largest-triangle-three-buckets), which keeps the point that changes the shape most in each bucket, so peaks and dips survive. The SVG never holds tens of thousands of points, so the screen, server rendering and exports all stay light.
Live example
Code for this example
createChart('#chart', {
type: 'line',
title: 'Sensor readings (2 × 20,000)',
zoom: true,
data: {
series: ['Unit 1', 'Unit 2'].map((name, k) => ({
name,
data: Array.from({ length: 20000 }, (_, i) => [new Date(Date.UTC(2026, 9, 1) + i * 60000), +(20 + k * 4 + Math.sin(i / 300 + k) * 6 + (i % 1733 === 0 ? 9 : 0)).toFixed(2)]),
})),
},
});| downsample | Behaviour |
|---|---|
| (default) | Lines and areas only: above 2,000 visible points, thin to about the plot width |
a number, e.g. 500 | Thin to this many when more are visible |
false | Draw every point |
- Tooltips, the crosshair and the keyboard move over the kept points. Zooming in (
zoom) samples just the visible range again, so more of the original points show. toCSV(), the downloaded CSV and the data table hold every value from before thinning.- The edges of gaps (
null) are kept, so lines still break where they did. With several series the points picked for each are merged so they all share the same x. - Bars are not thinned; aggregate thousands of bars first (daily or weekly totals). Many stacked areas are thinned along one shared outline instead of merging every series’ picks, so the point count does not grow.
Progressive rendering
When line, area and scatter series hold more than 5,000 points in all, the chart paints in steps: the loading placeholder (shimmering bars) shows at once, a coarse picture with about 150 points per series follows on the next frame, and full detail replaces it when the browser is idle, so the chart visibly sharpens. aria-busy is set meanwhile and the render event fires after the last step. Reload the example above to see it.
| progressive | Behaviour |
|---|---|
| (default) | Line, area and scatter charts above 5,000 points, when the data changes |
a number, e.g. 1000 | Above this many points |
true / false | Always / paint everything at once |
A resize or another option change repaints at once, without the steps. With reduced motion the sharpening fade is off. renderToSVG always returns the finished picture.
Other things kept light
- The hidden data table for screen readers holds the first 50 and last 50 rows and one note ("N more rows. Download the CSV for all of them."). Showing the table (Show table in the ⋯ menu or
table: true) builds every row then. The CSV always has everything. - The table, header, legend and tool buttons are rebuilt only when their content changes, not on resize or hover.
- Pointer moves update the tooltip at most once per frame, and the nearest x is found by binary search over the sorted positions.
- Scatter plots above 3,000 points draw points that land on the same pixel once, as a few translucent paths instead of one element per point; the tooltip still finds every original point (a grid index).