
ChartGPU is a data visualization library that leverages WebGPU to render interactive, hardware-accelerated charts with extreme performance. It handles datasets with millions of points while maintaining smooth frame rates above 100 FPS.
The high-performance charting library supports multiple series types, including line, area, bar, scatter, pie, and candlestick charts. Ideal for real-time dashboards, financial applications, or data visualization tools that require exceptional performance with large or streaming datasets.
Features
- WebGPU Hardware Acceleration: Renders charts using GPU compute shaders for parallel processing of large datasets.
- Streaming Data Support: Provides
appendData()method for real-time updates without full re-renders. - Built-in Interactions: Includes hover tooltips, crosshair tracking, and zoom controls with configurable trigger modes.
- Data Sampling: Implements LTTB (Largest Triangle Three Buckets) and OHLC sampling to maintain visual fidelity while reducing rendered points.
- Theme System: Ships with dark and light presets plus custom theme support for colors, typography, and grid styling.
- TypeScript Native: Written in TypeScript with full type definitions for configuration options and API methods.
- React Integration: Offers official React bindings via the chartgpu-react package.
Use Cases
- Financial Trading Platforms: Render candlestick charts with millions of historical price points and real-time tick updates at market speed.
- IoT Monitoring Dashboards: Display streaming sensor data from hundreds of devices with synchronized crosshair interactions across multiple time-series charts.
- Scientific Data Visualization: Plot large experimental datasets with scatter series where per-point sizing reveals data density patterns.
- Performance Analytics: Build interactive dashboards tracking application metrics with auto-scrolling time windows and configurable zoom ranges.
How To Use It:
1. Install the ChartGPU with NPM.
# NPM $ npm install @chartgpu/chartgpu
2. Create a wrapper in your HTML. Then initialize the chart instance in your JavaScript/TypeScript code.
import { ChartGPU } from 'chartgpu';
// Check if WebGPU is available in the browser
if (!('gpu' in navigator)) {
console.error('WebGPU not supported in this browser');
// Display fallback message to user
}
// Select the container element
const container = document.getElementById('chart');
// Define the chart options
const options = {
// Set internal grid padding
grid: { left: 60, right: 20, top: 20, bottom: 40 },
// Configure axis types
xAxis: { type: 'time', name: 'Timestamp' },
yAxis: { type: 'value', name: 'Price' },
// Define data series
series: [{
type: 'line',
name: 'Main Signal',
// Data format: [x, y] tuples
data: [[1700000000000, 10.5], [1700000060000, 15.2]],
lineStyle: { width: 2, opacity: 1 }
}]
};
// Initialize asynchronously (WebGPU requirement)
ChartGPU.create(container, options).then(chart => {
console.log('Chart is ready');
});3. Use the official React component wrapper to create charts in your React apps.
import { ChartGPUChart } from 'chartgpu-react';
import { useState } from 'react';
function MyChart() {
const [data, setData] = useState([[0, 10], [1, 20], [2, 15]]);
return (
<ChartGPUChart
options={{
series: [{
type: 'line',
data: data
}],
theme: 'light'
}}
// Chart updates automatically when options prop changes
/>
);
}4. Full configuration options.
grid(object): Controls the padding around the chart. Properties:left,right,top,bottom(numbers in CSS pixels). Defaults:{ left: 60, right: 20, top: 40, bottom: 40 }.xAxis(object): Configures the horizontal axis. Properties:type(string): ‘value’, ‘time’, or ‘category’. Note: ‘time’ expects timestamps in milliseconds.min(number): Explicit minimum domain value.max(number): Explicit maximum domain value.name(string): The label displayed near the axis.data(array): Array of strings. Only used whentypeis ‘category’.
yAxis(object): Configures the vertical axis. Properties:type(usually ‘value’),min,max,name.autoScroll(boolean): Iftrue, the chart automatically pans to follow new data appended viaappendData. Note: Only works when x-axisdataZoomis enabled and min/max are not set.animation(object | boolean): Controls transition effects. Properties:duration(number): Animation length in milliseconds (default 300).easing(string): Easing function (e.g., ‘linear’, ‘cubicOut’).delay(number): Delay before animation starts in milliseconds.
theme(string | object): Sets the visual style. Accepts ‘dark’, ‘light’, or a customThemeConfigobject.palette(array): An array of color strings to cycle through for series that don’t specify a color.dataZoom(array): Configures zoom interaction. Array of objects with properties:type(string): ‘slider’ (visible widget) or ‘inside’ (mouse wheel/drag).start(number): Initial start percentage (0-100).end(number): Initial end percentage (0-100).minSpan(number): Minimum zoom span constraint.maxSpan(number): Maximum zoom span constraint.
tooltip(object): Controls the pop-over info box. Properties:show(boolean): Toggle visibility.trigger(string): ‘axis’ or ‘item’.formatter(function): Custom callback(params) => stringto format content.
series(array): A list of series configuration objects. Common properties for all types:type(string): ‘line’, ‘area’, ‘bar’, ‘pie’, ‘scatter’, ‘candlestick’.name(string): The series name used in tooltips.data(array): The dataset. Usually[x, y]or[timestamp, open, close, low, high].color(string): The primary color for the series.sampling(string): Downsampling strategy (‘lttb’, ‘min’, ‘max’, ‘average’, ‘none’, or ‘ohlc’ for candlesticks).samplingThreshold(number): Point count threshold to trigger sampling (default 5000).
series(Line / Area Specific):lineStyle(object): Properties:width(pixels),opacity(0-1).areaStyle(object): Properties:color,opacity. (If present, renders a filled area).baseline(number): The filled area floor (Area series only).
series(Bar Specific):barWidth(string | number): Fixed width (px) or percentage string (e.g., ‘80%’).stack(string): Stack group ID. Bars with the same ID stack on top of each other.barGap(number): Gap between bars in the same group (ratio 0-1).itemStyle(object): Properties:borderRadius,borderWidth,borderColor.
series(Candlestick Specific):style(string): ‘classic’ (filled bodies) or ‘hollow’ (hollow for up-candles).sampling(string): Set to ‘ohlc’ for accurate data aggregation.data(array): UsesOHLCDataPointtuples:[timestamp, open, close, low, high].
series(Scatter Specific):symbolSize(number | function): The pixel radius of the points.mode(string): ‘points’ (default) or ‘density’ (heatmap).binSize(number): Bin size in CSS pixels (only for ‘density’ mode).densityColormap(string | array): ‘viridis’, ‘plasma’, ‘inferno’, or array of color strings.
series(Pie Specific):radius(array):[inner, outer](e.g.,['40%', '70%']).center(array):[x, y](e.g.,['50%', '50%']).data(array): Objects with{ value, name, color? }.
5. API methods.
/ Updates the chart configuration.
// This triggers a complete re-render of the scene.
chart.setOption({
series: [{ data: newCompleteDataset }]
});
// Appends data efficiently to an existing series.
// This is critical for high-performance real-time streaming.
// Parameters: seriesIndex (number), newPoints (array of tuples/objects)
chart.appendData(0, [[Date.now(), 25.4]]);
// Forces the chart to resize.
// Call this inside your window 'resize' event listener.
chart.resize();
// Cleans up all WebGPU resources and removes event listeners.
// Always call this before removing the DOM element to prevent memory leaks.
chart.dispose();
// Sets the zoom window programmatically.
// Parameters: start (percent), end (percent)
chart.setZoomRange(80, 100);
// Gets the current interaction position (crosshair X) in domain units.
// Returns null if the cursor is not active.
const xValue = chart.getInteractionX();
// Manually sets the crosshair position.
// Useful for synchronizing multiple charts.
chart.setInteractionX(timestampValue);6. Event handlers.
// Triggers when the user clicks on a data point.
chart.on('click', (params) => {
// params: { seriesIndex, dataIndex, value: [x, y], seriesName }
console.log('User clicked:', params.value);
});
// Triggers when the mouse hovers over a data point.
chart.on('mouseover', (params) => {
console.log('Hovering series:', params.seriesName);
});
// Triggers when the crosshair moves across the grid.
// Useful for updating external UI elements based on cursor position.
chart.on('crosshairMove', (params) => {
// params: { x: number | null, source: unknown }
console.log('Current X Domain:', params.x);
});FAQs:
Q: Does this work in all browsers?
A: No. It requires a browser with WebGPU support. This includes Chrome 113+, Edge 113+, and Firefox Nightly.
Q: Is it faster than Canvas-based libraries?
A: Yes, for large datasets. Canvas 2D is CPU-bound. ChartGPU leverages the GPU. This difference becomes noticeable once you exceed ~10,000 data points or require 60fps streaming.
Q: How do I handle window resizing?
A: You must listen to the window resize event. Then call chart.resize(). We recommend using a ResizeObserver on the container element for robustness.
Q: Why does my chart look blank?
A: Check your browser’s console. WebGPU requires a secure context (HTTPS or localhost). It will not run if the browser environment does not support the navigator.gpu API.
Changelog:
v0.3.2 (02/27/2026)
- Widened CartesianSeriesData to accept null entries for line and area series
- Added connectNulls option to line and area series configs
- Resolve connectNulls for line and area series in the options layer
- Add connectNulls filter in the data upload path
- Bypass sampling when data contains null gaps
- Add NaN gap detection to the line vertex shader
- Handle null gaps in area renderer vertex generation
- Fix connectNulls handling with columnar data formats
v0.3.1 (02/26/2026)
- Touch-friendly inside zoom for mobile: createInsideZoom now supports single-finger panning and two-finger pinch-to-zoom on touch devices using the existing ZoomState APIs.
- Mobile zoom reset button: New createZoomResetButton appears on touch devices when the chart is zoomed and lets users reset to the full domain with a single tap.
- Lifecycle-aware integration: The zoom reset button is only created when dataZoom includes an inside configuration, responds to theme changes, and is disposed with the chart coordinator.
- Expanded touch interaction tests: Vitest + jsdom tests now cover createInsideZoom touch gestures and createZoomResetButton behavior, visibility, and theming.
- Improved DOM test setup: jsdom has been added as a dev dependency to support DOM-based interaction tests in a Node environment.
v0.3.0 (02/26/2026)
- Adds a new AxisConfig.tickFormatter API for fully customizable axis tick label formatting on both value and time axes, including null-based label suppression for selectively hiding labels.
- Wires tickFormatter through the render pipeline, including renderAxisLabels and adaptive time-axis tick computation, so layout decisions are driven by the actual formatted label widths.
v0.2.9 (02/19/2026)
- Bugfixes
v0.2.8 (02/15/2026)
- Doc update
v0.2.7 (02/15/2026)
- Added a dataAppend event emitted by appendData() to support real‑time data tracking, cross‑chart coordination, and streaming sync utilities.
- Implemented external render mode (renderMode: ‘external’) with renderFrame(), needsRender(), and setRenderMode() so host apps can own the render loop and synchronize multiple charts in a single frame.
- Introduced an optional shared pipeline cache (createPipelineCache(device)) to dedupe GPUShaderModule, GPURenderPipeline, and GPUComputePipeline across charts on the same GPUDevice, reducing shader compilation overhead in dashboards.
- Added a streaming multi‑chart APM‑style dashboard example (5 charts, correlated metrics, programmatic annotations, dark theme) using a shared GPUDevice and pipeline cache.
- Upgraded the render coordinator to a 3‑pass 4x MSAA pipeline: main scene at 4x MSAA → blit → overlay at 1x.
- Improved visual quality for line, area, bar, and scatter series in multi‑chart scenarios without changing the existing public API.
- Shared GPUDevice and shared pipeline cache now enable more efficient multi‑chart rendering for complex dashboards.
- Ensured bigint type consistency in PipelineCache hashing logic to keep 64‑bit masking and FNV‑1a hash operations strictly on bigint and avoid implicit operand conversions flagged by static analysis.
- All new capabilities are opt‑in: existing single‑chart setups continue to function unchanged, while dashboards can opt into shared devices, pipeline caches, and external render mode for better coordination and performance.
v0.2.6 (02/11/2026)
- Shared GPUDevice for dashboards: Multiple ChartGPU instances can now share a single { adapter, device }, reducing redundant WebGPU initialization and making multi-chart dashboards more ergonomic.
- Optional create context: ChartGPU.create(container, options, context?) accepts a ChartGPUCreateContext with injected { adapter, device } to opt into shared-device mode when you already manage WebGPU yourself.
- Clear ownership semantics: Injected adapters/devices are treated as externally owned and are never destroyed by ChartGPU; canvas contexts are still unconfigured on dispose to avoid leaks while respecting host lifetime management.
- Device loss handling: A new ‘deviceLost’ chart event is emitted in shared-device mode so dashboards can react to device loss and propagate recovery or teardown logic consistently.
- Enhanced zoom sync behavior: Zoom range change semantics were refined to support auto-scroll isolation in sync groups, so one chart can auto-scroll while others stay pinned or follow according to group configuration.
- Multi-chart dashboard cookbook: New documentation and examples walk through building multi-chart dashboards with a shared GPU device and demonstrate the updated zoom event behavior and sync patterns.
v0.2.5 (02/11/2026)
- Update
v0.2.4 (02/10/2026)
- Update
v0.2.2 (02/04/2026)
- Add Series Toggling
- Refactor GPUContext to remove OffscreenCanvas support
v0.2.1 (02/03/2026)
- Update
v0.2.0 (02/01/2026)
- Add Annotations On Click – Remove Web Worker Support (Performance Was Negligible Given The Complexity)
v0.1.9 (01/28/2026)
- Add density heatmap mode for scatter plots
v0.1.8 (01/28/2026)
- Enhance device pixel ratio handling
v0.1.7 (01/28/2026)
- Worker thread offscreen canvas support
v0.1.9 (01/28/2026)
- Add density heatmap mode for scatter plots







