Skip to content

Mount, render & export

A Chart is inert until you materialize it. Three methods do that:

  • .mount(canvas, opts?)MountedPlot<T> — the full interactive path: the mount owns a renderer, a glyph atlas, three layers, a requestAnimationFrame loop, and a ResizeObserver.
  • .render(target)void — compile + emit into layers you already own.
  • .toSVG(opts?)SVGSVGElement — a static vector export.
const device = await (await navigator.gpu.requestAdapter())!.requestDevice();
const mounted = chart.mount(canvas, {
device,
interactions: { tooltip: true, crosshair: { axis: "x" } },
panZoom: true,
});

A GPUDevice is required when the mount has to create its own renderer / atlas — pass it via plot({ device }) or mount(canvas, { device }).

OptionTypeNotes
deviceGPUDeviceRequired unless you pass your own renderer.
build() => Chart<T>Rebuild closure called on each invalidate() — for charts derived from external state.
width / heightnumberFixed CSS size; disables auto-resize when both set.
dprnumberOverride devicePixelRatio.
autoResizebooleanTrack size via ResizeObserver. Default true unless fixed size.
autoFramebooleanInternal rAF loop. Default true.
pauseOnHiddenbooleanPause while document.hidden. Default true.
backgroundColorOverrides chart / theme background.
interactionsboolean | InteractionsConfigSee below.
transitionsboolean | TransitionsConfigAnimate on data / config change. Default on.
panZoomboolean | PanZoomConfigPointer pan/zoom on continuous scales. Off by default.
clipMarksbooleanClip marks to the inner plot panel. Default true.
partialRedrawbooleanDamage-tracked partial redraw. Default on.

Advanced bring-your-own hatches — renderer, layers, extraLayers, onFrameTiming, enablePipelineProfiling — let you share a renderer, supply your own layers, or hook frame timing.

interactions is true (defaults: hover tooltip on hit-testable geoms + snapping crosshair on continuous-x charts), false (all off), or an InteractionsConfig:

FieldDefaultWhat it does
tooltiponHover tooltip; content resolver overrides the body.
crosshairon (continuous x)Guide line; axis, color, followPointer.
selectionoffClick-to-select; exposes MountedPlot.selected.
brushoffDrag-to-rect; exposes MountedPlot.brushed.
legendonClick-to-toggle series visibility; exposes MountedPlot.hidden.
contextMenuoffRight-click / long-press menu (needs items or onTrigger).

The returned handle:

MemberTypeNotes
invalidate()voidSchedule a redraw next frame.
update(source?)voidSwap the chart (Chart<T>), the build closure (() => Chart<T>), or force a rebuild.
setData(data)voidReplace the data array.
resize(w?, h?)voidManual resize (re-reads bounds if no args).
setBackground(color | null)voidOverride / revert background.
toSVG(opts?)SVGSVGElementStatic export from the current spec + data.
destroy()voidTear down the loop, observers, signals, and owned GPU resources.
hovered / selected / brushed / hiddenread-only signalsSubscribe / peek interaction state.
viewportDataViewport | nullPresent only when panZoom was enabled.
pickAt(canvasX, canvasY){ plotFrameX, plotFrameY, dataX, dataY, frame } | nullScreen → data conversion through the active coord.
plotFrameFrameInner panel rect (union of all facet panels).
width / height / dpr / shapeCount / triangleCountnumberCurrent render stats.
renderer / axisLayer / marksLayer / hudLayer / overlayLayerrefsEscape hatches to internal pieces.

It also exposes imperative attach helpers: attachRangePresets(...), attachSeriesReadout(...), and attachBrush(...).

const unsub = mounted.hovered.subscribe((hit) => {
console.log(hit ? `over ${hit.geomKind}#${hit.dataIndex}` : "out");
});

Compile and emit into externally owned layers — use when the host already owns a Renderer2D and wants its own frame loop / timing.

interface RenderTarget {
axisLayer: Layer;
marksLayer: Layer;
hudLayer: Layer;
width?: number;
height?: number;
}
chart.render({ axisLayer, marksLayer, hudLayer, width: 800, height: 400 });
renderer.render([axisLayer, marksLayer, hudLayer]);

.render() only fills the three layers; you call the renderer yourself and manage resize / interactions. For everything else, prefer .mount().

A static, dependency-free vector export — no GPU device required.

const svg = chart.toSVG({ width: 600, height: 400 });
document.body.append(svg);

MountedPlot.toSVG() does the same from a live mount’s current spec + data.