API · Chart
Chart API
On this page
ChartGPU.create(container, options, context?)
import { ChartGPU } from '@chartgpu/chartgpu';
const container = document.getElementById('chart')!;
const chart = await ChartGPU.create(container, {
series: [{ type: 'line', data: [[0, 1], [1, 3], [2, 2]] }],
});
containermount target (ChartGPU owns a canvas inside it)optionsconfiguration (see Options & series)- Create-only options:
antialiasis applied at create (MSAA pipelines / texture manager).devicePixelRatiois a create-time policy: an explicit finite value freezes buffer + text-overlay DPR for the chart lifetime; when omitted, eachresize()re-reads livewindow.devicePixelRatio. Buffer size uses layoutclientWidth/clientHeight(not visualgetBoundingClientRect()under CSS zoom).setOptioncannot change either — dispose and recreate instead.
- Create-only options:
context?optional shared WebGPU{ adapter, device, pipelineCache? }
Sharing GPU resources (optional)
Shared GPUDevice
const adapter = await navigator.gpu.requestAdapter({ powerPreference: 'high-performance' });
const device = await adapter.requestDevice();
const chart1 = await ChartGPU.create(container1, opts1, { adapter, device });
const chart2 = await ChartGPU.create(container2, opts2, { adapter, device });
- If you inject
{ adapter, device }, charts do not calldevice.destroy()ondispose()(you own the device). - If you don’t inject, ChartGPU creates and destroys its own device.
- Charts created with an injected device can emit
'deviceLost'; on loss, recreate device + charts.
Pipeline cache (PipelineCache)
Share a cache to dedupe shader/pipeline creation across charts on the same device.
import { createPipelineCache } from '@chartgpu/chartgpu';
const pipelineCache = createPipelineCache(device);
await ChartGPU.create(a, optsA, { adapter, device, pipelineCache });
await ChartGPU.create(b, optsB, { adapter, device, pipelineCache });
- Cache is scoped to a single
GPUDevice(mixing devices throws).
ChartGPUInstance
Returned by ChartGPU.create(...).
See ChartGPU.ts for the full interface and lifecycle behavior.
Properties (essential):
options: Readonly<ChartGPUOptions>: the last user-provided options object (unresolved).disposed: boolean
Common methods:
setOption(...)update options and schedule a render.- Series identity: Prefer immutable series configs. When the same series element objects are re-passed (axes-only y/x range ticks), ChartGPU may reuse the previous resolved series array without re-scanning each series. To change data, color, visibility, or style, pass new series element objects (or a new
seriesarray). See Options & series — series array identity reuse.
- Series identity: Prefer immutable series configs. When the same series element objects are re-passed (axes-only y/x range ticks), ChartGPU may reuse the previous resolved series array without re-scanning each series. To change data, color, visibility, or style, pass new series element objects (or a new
appendData(seriesIndex, newPoints, options?)streaming append for cartesian series.- Formats
CartesianSeriesData(DataPoint[],XYArraysData,InterleavedXYData, band/errorBar payloads) orOHLCDataPoint[] - Optional
{ maxPoints }(per call, not sticky series state — omit later for unbounded growth):- If a single batch is ≥
maxPoints, keep only that batch’s tail (strict replace; prior points discarded). - Otherwise fixed-capacity ring: fill up to
maxPoints, then overwrite oldest slots (GPU modular writes — O(append), no full retained-window rewrite). Peak retained length / GPU reservation =maxPoints. - Prefer over sliding-window full
setOptionfor high-rate streaming (fixed-capacity ring; not sticky series construction state). - When both
maxPointsis set andtooltip.show === false, ChartGPU’s hit-test columnar store is not updated on append (dual-store relief); coordinator/GPU still apply the ring.
- If a single batch is ≥
- Device storage cap (unbounded append)series buffers are storage-bound. When growth would exceed
min(maxBufferSize, maxStorageBufferBindingSize)(often 128 MiB ≈ 16.7M xy points on Chrome/Metal), ChartGPU auto-windows to that point budget (same ring policy asmaxPoints) so the x-domain stays in sync with GPU-resident data. The hit-test store (when tooltips are on) applies the same effective window — GPU and interaction history retain one chronological window. Without this, the axis could keep expanding while the series stopped short of the right edge. Pass an explicit{ maxPoints }when you want a smaller sliding window (still hard-clamped by the device budget). - Not for heatmap / surface3d / pie — use the dedicated update APIs below (or full
setOption). - Types
updateHeatmap(seriesIndex, update)2D only — streaming / partial update fortype: 'heatmap'(replaceZ/appendColumns+scrollX /appendRows+scrollY). Not cartesianappendData. See Options & series.updateSurface3D(seriesIndex, update)3D only — partial update forsurface3d(replaceY/appendColumns/appendRows). No-op on 2D. See 3D charts.setCamera(partial)resize(),dispose()hitTest(e)pointer hit-test (coordinates + optional match)setInteractionX(...)/setCrosshairX(...)getZoomRange()/setZoomRange(...)getPerformanceMetrics()/getPerformanceCapabilities()/onPerformanceUpdate(...)getRenderMode()/setRenderMode(...)/needsRender()/renderFrame()
Data upload and scale/bounds derivation occur during createRenderCoordinator.ts RenderCoordinator.render() (not during setOption(...) itself).
External Render Mode
Set renderMode: 'external' to run ChartGPU inside your own render loop.
const chart = await ChartGPU.create(container, { renderMode: 'external', series: [...] });
function loop() {
if (chart.needsRender()) chart.renderFrame();
requestAnimationFrame(loop);
}
loop();
GPU submit timing
renderFrame() encodes the frame but defers device.queue.submit to a
queueMicrotask. Multi-chart dashboards that share one GPUDevice and call
renderFrame() on every surface in the same JS turn therefore collapse into a
single batched submit (shared-device multi-chart present).
If you need GPU work on the queue before onSubmittedWorkDone() (or any
immediate post-submit fence), drain the microtask first:
chart.renderFrame();
await Promise.resolve(); // flush batched submit
await device.queue.onSubmittedWorkDone();
dispose() flushes any pending batched submit for that chart’s device before
destroying textures/buffers.
Example: examples/external-render-mode/.
Chart sync (connectCharts)
Sync crosshair/tooltip between charts (default) and optionally sync zoom.
- Zoom sync only has effect when all connected charts have data zoom enabled.
import { connectCharts } from '@chartgpu/chartgpu';
const disconnect = connectCharts([chartA, chartB], { syncZoom: true });
API reference for the linked @chartgpu/chartgpu package (v0.4.0). Source on GitHub.