Radiant Charts is built on a pure HTML5 Canvas engine — no SVG, no DOM nodes per data point. This architecture gives it a fundamental performance advantage for large datasets, real-time streaming, and animation-heavy dashboards.
SVG-based charting libraries create one DOM element per data point. A scatter plot with 10,000 points means 10,000 <circle> elements, each triggering layout, paint, and composite passes in the browser. Canvas draws everything to a single bitmap — the browser sees one element regardless of how many data points are rendered.
| Data Points | SVG (typical) | Canvas (Radiant) |
|---|---|---|
1,000 | ~60 fps | ~60 fps |
10,000 | ~15-30 fps | ~60 fps |
50,000 | ~2-5 fps | ~45-55 fps |
100,000+ | Unusable | ~30-40 fps |
For datasets exceeding 50,000 points, consider passing only the visible window of data to the chart. Combine this with pan/zoom interaction to let users explore the full range without loading everything at once.
const visibleData = fullData.slice(startIndex, endIndex);
<RadiantChart
options={{
data: visibleData,
series: [{ type: 'line', xKey: 'time', yKey: 'value' }],
}}
height={400}
/>For real-time dashboards that receive data continuously, use the imperative appendData method instead of replacing the entire data array. This pushes new records into an internal buffer and triggers processData → performLayout → render without a React re-render, making it safe to call at 60 fps.
const chartRef = useRef<RadiantChartHandle>(null);
useEffect(() => {
const ws = new WebSocket('wss://data-feed.example.com');
ws.onmessage = (event) => {
const point = JSON.parse(event.data);
chartRef.current?.appendData([point], 500); // keep last 500 points
};
return () => ws.close();
}, []);
<RadiantChart ref={chartRef} options={baseOptions} height={400} />appendData(newData, maxBuffer) caps the internal buffer size. Older points are dropped from the front. This prevents unbounded memory growth in long-running dashboards.Animations add visual polish but cost frame time. When updating the chart many times per second (e.g. streaming), disable animations to maximise throughput:
options={{
data,
series: [{ type: 'line', xKey: 'time', yKey: 'value' }],
animation: { enabled: false },
}}Series implementations in Radiant Charts reuse scene-graph shape objects between render cycles. Instead of clearing all shapes and recreating them, the engine:
This avoids garbage-collection pressure from rapid object creation and enables smooth animation re-targeting — a shape mid-animation transitions seamlessly to its new target rather than snapping to the old target before animating to the new one.
The exportToPng() method on the chart ref triggers a client-side PNG download. The canvas background is always opaque (synced from the theme) so exported images never have a transparent background.
const chartRef = useRef<RadiantChartHandle>(null);
<button onClick={() => chartRef.current?.exportToPng('my-chart')}>
Download PNG
</button>
<RadiantChart ref={chartRef} options={options} height={400} />