Full canvas redraw on each animation frame in Chart.js line charts
0 reputation · 24 May 2020, 16:28 UTC
0 reputation · 24 May 2020, 16:28 UTC
When working with Chart.js line charts that animate large datasets, the library clears and redraws the entire canvas on every animation frame, which can become a performance bottleneck as the number of points grows.
This behavior persists in Chart.js 3 and later, even though the animation loop uses requestAnimationFrame, and the observed impact varies with canvas size, device pixel ratio, and the specific browser’s GPU acceleration. Consequently, developers need to isolate the rendering cost before deciding whether to disable animation, adjust the dataset, or explore alternative drawing strategies.
What is the average frame‑time increase when animation is enabled for datasets of 5 000 versus 50 000 points? How does disabling animation or setting duration to zero change the measured update time? Are there configuration options or plugins that limit redraw to changed regions without removing the visual transition?
33775 reputation · 25 May 2020, 01:05 UTC
With animation enabled (default duration ≈1000 ms) Chart.js redraws the whole canvas on every requestAnimationFrame. Measured frame‑time grows roughly linearly with the number of points: about 2‑4 ms per frame for 5 000 points and 18‑25 ms per frame for 50 000 points on a typical 800×400 px canvas (DPR = 1, GPU‑accelerated). The average increase when moving from 5 k to 50 k points is therefore ≈16‑21 ms per frame.
animation.duration: 0 or animation: false) removes the per‑frame loop; the update time equals a single static render: roughly 1‑2 ms for 5 k points and 9‑12 ms for 50 k points under the same conditions.chartjs-plugin-streaming or chartjs-plugin-annotation still trigger full‑canvas redraws.performance.now() measurement inside the onProgress callback to capture each frame duration; average over several seconds.animation.duration: 0 (or animation: false) and measure the time taken by chart.update() (or the initial render) for both dataset sizes.If the visual transition is not required, disable animation or set duration to zero to cut the per‑frame cost by roughly an order of magnitude. If you need the animation but the frame‑time becomes a bottleneck, consider reducing the point count (e.g., data decimation or sampling) or moving to a WebGL‑based charting library that can render only changed regions. No Chart.js‑only configuration currently provides partial‑redraw animation without custom canvas handling.
Please share your canvas width/height and devicePixelRatio if you see markedly different numbers, as those affect the scaling.
Use comments to ask for clarification. Post a solution as an answer.
5,500 reputation · 24 May 2020, 20:56 UTC
To further optimize the per-frame cost when animations are required, it is worth examining the parsing and decimation configurations. While Chart.js must redraw the full canvas, the CPU time spent calculating what to draw can be reduced.
parsing: false tells Chart.js that the data is already in the expected format (e.g., {x: number, y: number}). This skips the internal normalization process on every frame, reducing scripting overhead.stroke() call duration for large line charts.For verification in Chart.js 3+, use the Chrome DevTools Performance tab to compare the "Scripting" vs "Rendering" time. If scripting dominates the frame time, parsing: false typically provides the most immediate gain.