BlazePlot
Fast WebGL2 plotting engine for the browser 🔥
GPU-native, minimal DOM. Built on WebGL2 + regl . No Canvas2D, no SVG, no layout thrashing.
Installation Quick start< div id = " chart" style = " width:100%;height:400px" > </ div> import { Chart } from "blazeplot" ;
const container = document. getElementById ( "chart" ) ;
const chart = new Chart ( container) ;
const series = chart. addSeries (
{ mode : "line" , capacity : 1_000_000 , downsample : "minmax" } ,
{ color : [ 0.3 , 0.6 , 1.0 , 1.0 ] } ,
) ;
chart. setViewport ( { xMin : 0 , xMax : 1000 , yMin : - 2 , yMax : 2 } ) ;
chart. start ( ) ;
const xs = new Float64Array ( 256 ) ;
const ys = new Float32Array ( 256 ) ;
let t = 0 ;
function push ( ) {
for ( let i = 0 ; i < 256 ; i++ ) {
xs[ i] = t++ ;
ys[ i] = Math. sin ( t * 0.01 ) * 0.5 + Math. random ( ) * 0.01 ;
}
series. append ( xs, ys) ;
requestAnimationFrame ( push) ;
}
push ( ) ; Features
WebGL2 rendering
GPU-accelerated plot rendering from the ground up. No Canvas2D fallback. Axis labels use lightweight DOM layers.
Flexible data model
Streaming ring buffer or static arrays. Bring your own data shape.
LOD downsampling
Min/max pyramid for efficient line rendering at any zoom level — sparse views show raw points, dense views show vertical segments.
Pan & zoom
Pointer/touch pan and wheel zoom via Camera2D. Customizable viewport policies.
Grid lines
Data-anchored grid rendered as WebGL line lists.
Axis labels
Smart tick generation with DOM labels. Per-axis inside/outside positioning; outside axes reserve real layout gutters.
Multi-series
Independent buffers, styles, and visibility per series. Line, area, scatter, and bar modes are supported.
Benchmark overlay
Built-in fps, frame time, vertex count, draw calls.
ResizeObserver
Automatic DPR-aware canvas sizing.
APIChart
Signature
Description
new Chart(container, options?)
Create a chart inside an HTML container element. The chart owns the plot canvas and axis layout.
chart.addSeries(config, style?)
Add a data series. Returns SeriesStore.
chart.removeSeries(series)
Remove a previously added series.
chart.setViewport({ xMin, xMax, yMin, yMax })
Set the visible data range.
chart.resize(dpr?)
Resize the internal plot canvas to match its CSS size × DPR.
chart.start()
Start the render loop (rAF).
chart.stop()
Stop the render loop.
chart.canvas
Read-only access to the internal plot canvas.
chart.getFrameStats(target?)
Copy per-frame benchmark counters into a reusable object.
chart.dispose()
Dispose GPU resources, observers, input handlers, and owned DOM layout.
ChartOptions
Property
Default
Description
viewportPolicy?
—
Custom pan/zoom/viewport behavior hooks.
grid?
true
Show grid lines.
gridStyle?
{ color: [0.22,0.30,0.44,0.45] }
Grid line color and width.
axes?
true
Show axis tick labels. true/false, or per-axis { x?: boolean | AxisConfig, y?: boolean | AxisConfig }.
AxisConfig
Property
Default
Description
visible?
true
Show this axis.
position?
"inside"
"inside" draws labels over the plot; "outside" reserves a real DOM gutter and shrinks the plot canvas.
new Chart ( canvas, {
axes: { x: { position: "outside" } , y: true }
} ) ; ChartFrameStats
Field
Description
fps
Instantaneous render-loop FPS.
frameMs
Milliseconds spent in render().
pointsRendered
Number of vertices drawn this frame.
drawCalls
Number of GPU draw calls this frame.
uploadBytes
Bytes uploaded to GPU this frame.
renderMode
"none" / "raw" / "minmax" / "points" / "bars" / "area" / "mixed".
SeriesStore
Signature
Description
series.append(xs, ys)
Append typed arrays of X and Y values (streaming).
series.clear()
Clear all data and reset.
series.setVisible(v)
Toggle visibility.
series.visible
Current visibility state.
series.length
Number of samples buffered.
SeriesConfig
Property
Description
mode
"line" / "area" / "scatter" / "bar" / "envelope" (envelope roadmap-only).
capacity
Ring buffer capacity (samples).
downsample
"minmax" or "none". Min/max LOD applies to line rendering; area/scatter/bar skip LOD.
SeriesStyle
Property
Default
Description
color
[0.3, 0.6, 1.0, 1.0]
RGBA float color.
lineWidth
1
Line width in pixels.
pointSize
4
Scatter point size in CSS pixels.
barWidth
0.8
Bar width in data-space X units.
baseline
0
Area/bar baseline in data-space Y units.
fillColor
line color with 25% alpha
Area fill RGBA color.
ViewportPolicyinterface ViewportPolicy {
beforePan? ( camera: Camera2D, intent: PanIntent) : PanIntent | null ;
beforeZoom? ( camera: Camera2D, intent: ZoomIntent) : ZoomIntent | null ;
beforeRender? ( camera: Camera2D) : void ;
} Lower-level primitivesCamera2D, RingBuffer, MinMaxPyramid, AxisController are exported for advanced use cases.
Architecturesrc/
core/ # Data model — series, datasets, LOD
render/ # GPU abstraction + regl backend
interaction/ # Camera, input, axis ticks
ui/ # Orchestrator (Chart) Developmentbun install
bun run dev
bun run build
bun run build:js
bun test
bun run typecheck Package buildOutput:
dist/index.js ES module
dist/index.d.ts TypeScript declarations Why WebGL2?Canvas2D and SVG are CPU-bound — every point becomes a draw call or a DOM node. BlazePlot keeps plot data on the GPU and streams only visible vertices; DOM is limited to chart layout and labels. For dense line plots (millions of points), interactive scatter, or real-time streaming, the difference is orders of magnitude.