ruviz
v0.14.2
Published
Browser-first JS/TS SDK for ruviz WebAssembly rendering
Readme
ruviz
ruviz is the published browser-first JS/TS SDK for the ruviz plotting
runtime.
It wraps the raw wasm-bindgen bridge in the Rust crate ruviz-web with a
higher-level API for static export, interactive canvas sessions, worker-backed
rendering, and reactive demos.
Install
npm install ruvizThe package ships as ESM. Browser apps should use a bundler or runtime that can
load WebAssembly and module workers from package-relative import.meta.url
references.
The public package entrypoints are:
import { createPlot, createWorkerSession } from "ruviz";
import initRaw, { JsPlot } from "ruviz/raw";
await initRaw();
const rawPlot = new JsPlot();Quick Start
import { createPlot } from "ruviz";
const plot = createPlot()
.line({ x: [0, 1, 2, 3], y: [0, 1, 4, 9] })
.title("Quadratic")
.setXLabel("x")
.setYLabel("y = x^2");
await plot.save({ format: "png", fileName: "quadratic.png" });Interactive Canvas Sessions
Mount a plot into a normal HTML canvas:
import { createCanvasSession, createPlot } from "ruviz";
const canvas = document.querySelector("canvas")!;
const session = await createCanvasSession(canvas);
await session.setPlot(
createPlot().line({ x: [0, 1, 2], y: [0, 1, 0] }).title("Interactive Plot"),
);
session.render();Use createWorkerSession(...) when you want OffscreenCanvas worker rendering:
import { createPlot, createWorkerSession } from "ruviz";
const canvas = document.querySelector("canvas")!;
const session = await createWorkerSession(canvas, {
backendPreference: "auto",
fallbackToMainThread: true,
});
await session.setPlot(createPlot().scatter({ x: [0, 1, 2], y: [2, 1, 3] }));
session.render();When Worker, OffscreenCanvas, or transferControlToOffscreen() is missing,
createWorkerSession() returns a WorkerSession in mode === "main-thread" by
default. Pass { fallbackToMainThread: false } to throw instead.
Both createCanvasSession() and createWorkerSession() default to
autoResize: true and bindInput: true, so pointer, wheel, and resize events
are wired automatically unless you disable them.
WebGPU 3D
Create and mount a 3D plot in one fluent expression:
import { surface } from "ruviz";
const canvas = document.querySelector("canvas")!;
const session = await surface(
[-1, 0, 1],
[-1, 0, 1],
[
[2, 1, 2],
[1, 0, 1],
[2, 1, 2],
],
)
.title("z = x² + y²")
.mount(canvas);
// Optional: the session already renders after mount, input, and resize.
session.render();Use .axisAspect(1, 2, 1).stableScale() for a fixed X:Y:Z plotting box that
keeps its framing while rotating. Use .equalScale().stableScale() when equal
data units must have equal lengths, such as physical geometry. Fixed box ratios
and equal data units differ when axis ranges differ. Stable scale reserves room
for every orientation; explicit zoom and resize still change the view.
The top-level scatter3d(x, y, z), line3d(x, y, z), surface(x, y, z),
and wireframe(x, y, z) factories accept arrays or typed arrays.
createPlot3d() exposes the same series methods on a discoverable builder.
Surface grids may be a flat row-major array or one row per y value as above.
Mounting an HTMLCanvasElement binds input and resize handling automatically.
Series methods append, matching Rust: surface(...).wireframe(...) keeps both.
For replacement, call builder.clearSeries().surface(...). Existing mounted
sessions keep their own scene when the builder changes.
Pass onError: (error) => ... to mount() to handle scheduled rendering and
browser-input failures. session.error retains the last failure and clears after
a successful frame. Call session.render() to retry a transient failure; if
session.needsRecreate() is true, call dispose() and mount a fresh session.
Failures preserve the last presented frame where the browser surface remains
available. Initial mounting failures reject the mount() promise. Without an
error callback, scheduled failures are logged to the console.
The same builder works inside a worker after the main thread transfers its canvas:
import { createPlot3d } from "ruviz";
declare const offscreenCanvas: OffscreenCanvas;
declare const devicePixelRatioFromMainThread: number;
const x = [0, 1, 2];
const y = [0, 1, 0];
const z = [1, 2, 3];
const session = await createPlot3d()
.scatter3d(x, y, z)
.mount(offscreenCanvas, { scaleFactor: devicePixelRatioFromMainThread });Worker code forwards input and resize messages through the session's
camel-cased methods such as pointerMove(...), wheel(...), and resize(...).
Rendering requests are coalesced to one submission per animation frame.
Plot Types
The fluent builder currently supports:
line({ x, y })andscatter({ x, y })bar({ categories, values, style: { orientation: "horizontal" } })(orientation is optional;"vertical"is the default)histogram(values)andboxplot(values)(box plots accept the same optionalstyle.orientationbars do)heatmap(rows)whererowsis a rectangularnumber[][]errorBars({ x, y, yErrors })errorBarsXY({ x, y, xErrors, yErrors })kde(values)andecdf(values)contour({ x, y, z })wherez.length === x.length * y.lengthpie(values, labels?)radar({ labels, series })violin(values)polarLine({ r, theta })
number[], Float64Array, and other ArrayLike<number> values are accepted
for numeric inputs. createObservable(...) can drive line, scatter, bar,
histogram, boxplot, and error-bar inputs. createSineSignal(...) can be used as
the y input for line and scatter plots.
Reactive Helpers
The package also exports:
createObservable(...)for mutable numeric seriescreateSineSignal(...)for time-varying demo inputscreatePlotFromSnapshot(...)for rehydratingplot.toSnapshot()outputgetRuntimeCapabilities()for browser capability checksregisterFont(...)for custom browser text faces
Which Package Should You Use?
- Use npm
ruvizfor browser apps in JS/TS. - Use the Rust crate
ruviz-webif you need the raw wasm bridge. - Use the root Rust crate
ruvizfor native Rust plotting.
Docs and Examples
- VitePress docs source:
packages/ruviz/docs/ - TypeScript examples:
packages/ruviz/examples/ - Raw Rust bridge: https://github.com/Ameyanagi/ruviz/tree/main/bindings/wasm
- Root project README: https://github.com/Ameyanagi/ruviz/blob/main/README.md
Local Development
From the repository root:
bun install
bun run --cwd packages/ruviz build:js
bun run --cwd packages/ruviz build
bun run --cwd packages/ruviz docs:devbuild:js runs the TypeScript build against existing generated wasm bindings.
build also rebuilds the wasm package before compiling TypeScript.
Session cleanup
Use detach() on a 2D CanvasSession or WorkerSession to clear its plot while
keeping input and resize bindings. Call setPlot(...) to attach another plot.
Use dispose() when removing the session from your application; it removes
bindings and terminates a worker. Dispose a 3D session before mounting a replacement.
destroy() remains a compatibility alias: it means detach() for 2D and
dispose() for 3D. New code should use the explicit names above.
