Charts, configured in code.
Build canvas charts from a single series or a coordinated grid of traces. FastPlotJs covers five 2D families, interactions and renderer-neutral Node scenes. Optional Rust runtimes accelerate supported paths; four 3D families are experimental.
From points to perspective.
Two series, one shared view. Drag to zoom into the data, or reset to see the complete chart.
Installation
Install the published package in a project with a JavaScript bundler. The package exports ESM and TypeScript declarations.
npm install fastplotjs
Import from the package root. Browser chart examples use a canvas element; Node scene generation does not need a browser.
import { createChart, plot } from "fastplotjs";
Your first chart
Put a canvas in your page, then call createChart after the element exists. This uses the public line chart API.
<canvas id="chart" width="800" height="400"></canvas>
import { createChart } from "fastplotjs";
const canvas = document.getElementById("chart");
const chart = createChart(canvas, {
type: "line",
engine: "auto",
data: [
{ x: 0, y: 12 },
{ x: 1, y: 18 },
{ x: 2, y: 15 },
{ x: 3, y: 24 },
],
axes: { show: true },
}, { color: "#1768eb", lineWidth: 2 });
Keep the returned chart instance if you need to update data, inspect interaction state, or destroy it later.
Data and traces
data supplies one series; traces supplies multiple named series. Each trace owns its points and can override family styling or bind to a subplot. Choose one data approach per chart.
typeThe chart family, such as line or bar.data / tracesUse data for one series, or traces for multiple named series.engineauto, ts, or strict rust.axesCartesian scale, tick, grid, and label options.Family data shapes: line, bar, and polar use { x, y }; heatmap uses { x, y, value }; wonderplot accepts optional value, size, and opacity channels; 3D uses finite numeric { x, y, z }.
For multi-trace input, provide a trace array. Each trace owns its data and can carry a name and color.
createChart(canvas, {
type: "line",
traces: [
{ name: "North", color: "#1768eb", data: [{ x: 0, y: 10 }, { x: 1, y: 15 }] },
{ name: "South", color: "#00a7a1", data: [{ x: 0, y: 8 }, { x: 1, y: 12 }] },
],
legend: true,
});
Choose a chart
The five current 2D families share createChart(canvas, options). Set type and put family-specific options under the matching key. The four 3D families below are experimental.
Line and area
Use ordered { x, y } points. x can be numeric or datetime input; null y values form gaps. Multiple traces give each series a name and color. Interpolation supports linear, smooth, and step-before/after/center; patterns include solid, dashed, dotted and dash-dot.
createChart(canvas, {
type: "line",
traces: [
{ name: "Actual", color: "#1768eb",
data: [{ x: 0, y: 10 }, { x: 1, y: 17 }, { x: 2, y: 14 }] },
{ name: "Target", color: "#00a7a1",
data: [{ x: 0, y: 12 }, { x: 1, y: 15 }, { x: 2, y: 18 }] },
],
lineStyle: { interpolation: "smooth", lineWidth: 2 },
markers: { show: true, shape: "circle", size: 5 },
areaFill: { show: true, opacity: 0.12, baseline: "zero" },
axes: { show: true }, legend: true,
});
Line options also include pointLabels, errorBars, trendline, and connectGaps. Use references.lines or references.bands for Cartesian thresholds.
Bar charts
Bars pair a category in x with a numeric y. Declare category order on the axis. The bar mode is grouped, stacked, or normalized (100% stacking); orientation can be vertical or horizontal.
createChart(canvas, {
type: "bar",
traces: [
{ name: "2025", color: "#1768eb",
data: [{ x: "Jan", y: 12 }, { x: "Feb", y: 18 }] },
{ name: "2026", color: "#00a7a1",
data: [{ x: "Jan", y: 15 }, { x: "Feb", y: 20 }] },
],
axes: { show: true, xAxes: { x: { categories: ["Jan", "Feb"] } } },
bar: { mode: "grouped", orientation: "vertical",
barWidthRatio: 0.7, cornerRadius: 4,
valueLabels: { show: true, position: "outside-end" } },
legend: true,
});
Change mode to stacked for totals or normalized for shares of each category. Bar borders, corners and labels can be overridden per trace. Floating ranges and horizontal layouts are also supported.
Polar windrose
Polar data uses x for a direction and y for radial magnitude. Give categorical directions an explicit angleCategories order. Sectors can be grouped or stacked; the radial scale can be linear or logarithmic.
const directions = ["N", "E", "S", "W"];
createChart(canvas, {
type: "polar",
traces: [
{ name: "Morning", color: "#1768eb",
data: [{ x: "N", y: 5 }, { x: "E", y: 12 },
{ x: "S", y: 8 }, { x: "W", y: 4 }] },
{ name: "Evening", color: "#00a7a1",
data: [{ x: "N", y: 3 }, { x: "E", y: 7 },
{ x: "S", y: 11 }, { x: "W", y: 6 }] },
],
polar: { mode: "windrose", sectorMode: "stacked",
angleCategories: directions, startAngleDegrees: -90,
grid: { rings: 4, angleLabels: true }, sectorLabels: true },
interactions: { polarRotate: true }, legend: true,
});
Use sectorWidthDegrees, gaps, inner/outer radius ratios, grid rings/spokes, labels and vectors for richer windroses. getPolarRotation() and setPolarRotation() expose rotation state.
Heatmap
Each cell is { x, y, value }. x and y can be ordered string categories or numeric positions; value drives color. Explicit category arrays keep sparse grids in the intended order.
createChart(canvas, {
type: "heatmap",
data: [
{ x: "Mon", y: "AM", value: 12 },
{ x: "Tue", y: "AM", value: 34 },
{ x: "Mon", y: "PM", value: 27 },
{ x: "Tue", y: "PM", value: 48 },
],
heatmap: {
xCategories: ["Mon", "Tue"], yCategories: ["AM", "PM"],
minValue: 0, maxValue: 50,
colorStops: [
{ offset: 0, color: "#172554" },
{ offset: 0.5, color: "#2563eb" },
{ offset: 1, color: "#fef08a" },
],
cellGap: 2, cornerRadius: 3,
cellLabels: true, colorScaleLegend: true,
},
});
Options include linear or logarithmic color scale, missing-cell treatment, labels, guides and borders. A logarithmic color scale requires positive values.
Wonderplot
A wonderplot places markers at x/y while separate value, size, and opacity fields drive color, radius and alpha. These channels can use independent scales.
createChart(canvas, {
type: "wonderplot",
data: [
{ x: 1, y: 3, value: 10, size: 30, opacity: 80 },
{ x: 2, y: 5, value: 70, size: 90, opacity: 45 },
{ x: 3, y: 4, value: 40, size: 55, opacity: 65 },
],
axes: { show: true },
wonderplot: {
markerShape: "hexagon", markerSize: 6,
colorScale: { minValue: 0, maxValue: 100,
lowColor: "#e0f2fe", highColor: "#7c3aed" },
sizeScale: { minValue: 0, maxValue: 100, minSize: 4, maxSize: 14 },
opacityScale: { minValue: 0, maxValue: 100,
minOpacity: 0.25, maxOpacity: 1 },
colorScaleLegend: true,
},
});
Marker shapes include circle, square, diamond, triangle, pentagon and hexagon. Labels and borders can be set globally or per trace. Positive color values can use a logarithmic color scale.
Axes and scales
Cartesian axes support linear, logarithmic and datetime scales. x input for datetime accepts ISO strings, Date objects or Unix milliseconds. Logarithmic data must be positive. Named x and y axes control ticks, grids, labels, ranges, titles and top/bottom or left/right sides.
createChart(canvas, {
type: "line",
data: [{ x: 1, y: 10 }, { x: 2, y: 100 }],
axes: {
show: true,
xAxes: { x: { grid: true, ticks: 4 } },
yAxes: { y: { scale: "logarithmic", grid: true, title: "Value" } },
},
});
Use categories for ordered category axes. Further axis options include explicit tickValues, minor ticks, label formatters, label rotation/collision, padding and date/time formatting. viewport sets an initial visible range; references.lines and references.bands add threshold guides.
Subplots and shared axes
Arrange charts in rows and columns. A trace identifies its subplot; each subplot selects named axes. Reuse an axis ID for a shared scale, or give cells independent axes. Rows and columns may be numbers or weighted tracks.
createChart(canvas, {
type: "line",
traces: [
{ subplot: "pressure", color: "#1768eb",
data: [{ x: 0, y: 80 }, { x: 1, y: 85 }] },
{ subplot: "temperature", color: "#ef4444",
data: [{ x: 0, y: 21 }, { x: 1, y: 24 }] },
],
subplots: {
layout: { rows: [{ weight: 2 }, { weight: 1 }], columns: 1 },
items: {
pressure: { row: 0, column: 0, xAxis: "time", yAxis: "pressure" },
temperature: { row: 1, column: 0, xAxis: "time", yAxis: "temperature" },
},
},
axes: {
show: true,
xAxes: { time: { title: "Time", grid: true } },
yAxes: { pressure: { title: "Pressure" },
temperature: { title: "Temperature" } },
},
});
Viewport controls can target a subplotId. viewportGroup links otherwise separate axes for navigation.
Styling, labels, and guides
Chart-level title, subtitle, backgrounds, margin, legend, and style control presentation. Trace color and family options override shared defaults. Text, axes, plot area, legend and tooltip have their own style branches.
createChart(canvas, {
type: "line",
title: "Monthly output", subtitle: "Units produced",
backgroundColor: "#f8fafc",
plotAreaBackgroundColor: "#ffffff",
traces: [{ name: "Output", color: "#1768eb",
data: [{ x: 1, y: 12 }, { x: 2, y: 19 }] }],
markers: { show: true, shape: "diamond", size: 6 },
pointLabels: true,
legend: { show: true, position: "top-right" },
references: { lines: [{ axis: "y", value: 15,
label: "Target", pattern: "dashed" }] },
style: { text: { color: "#1f2937" } },
});
Labels may be suppressed when space is tight; give essential chart data an accessible text summary. responsive, explicit width/height and instance resize() support different layout strategies.
Interactions
Interaction options are opt-in. Enable zoom on a Cartesian chart, then use the chart instance to read or change viewport state.
const chart = createChart(canvas, {
type: "line",
data: [{ x: 0, y: 2 }, { x: 1, y: 5 }],
interactions: { zoom: true },
});
const viewport = chart.getViewport();
chart.resetZoom();
Use interactions.zoom for wheel/drag/pinch, pan for movement, and tooltip, crosshair, pointClick or pointSelection for inspection. The instance offers zoomIn(), zoomOut(), pan(), autoscale(), getViewportControlState(), and on("viewportChange", handler). Polar rotation and experimental 3D camera control have family-specific methods. Area selection returning every original source point inside a drawn region is a future requirement, not a current API.
Data updates and synchronization
Update a chart instance without recreating its canvas. Use setData for one series, setTraces or setTraceData for multiple series, and appendData for incremental points. updateOptions changes presentation or configuration.
chart.setData([{ x: 0, y: 12 }, { x: 1, y: 20 }]);
chart.appendData([{ x: 2, y: 24 }]);
chart.updateOptions({ lineStyle: { pattern: "dashed" } });
const state = chart.getChartState();
if (state) otherChart.setChartState(state, { emit: false });
getDataState()/setDataState() handle data alone; chart state includes navigation, visibility and selection for synchronization. Set emit: false on a receiving chart to avoid two-way event loops.
Engines
ts selects the TypeScript implementation. auto uses an available native Node or initialized browser WASM runtime where a family builder supports it, with TypeScript fallback. rust is strict: missing runtime or unsupported family is an error. Select a mode explicitly when fallback behavior matters.
import { initWasmPlotEngine, getWasmPlotEngineStatus } from "fastplotjs";
await initWasmPlotEngine();
console.log(getWasmPlotEngineStatus());
WASM initialization is asynchronous; inspect its status before relying on acceleration. The package also exports Node native initialization/status helpers and a last-WASM-init-error helper. The experimental 3D families currently use the TypeScript scene path.
Node scenes and export
Use plot to produce a renderer-neutral scene without a browser. Unlike createChart, it needs explicit width and height. renderToCanvas draws into a supplied canvas.
import { plot } from "fastplotjs";
const scene = plot({
type: "line",
width: 800,
height: 400,
engine: "ts",
data: [{ x: 0, y: 12 }, { x: 1, y: 18 }],
});
console.log(scene.primitives.length);
The existing renderToPNG() API has a placeholder payload contract; it is not a general PNG encoder. For the four experimental 3D families, renderScene3dToSVG(options) returns a static SVG without a DOM. Asynchronous renderScene3dToPNG(options) requires the optional native Node addon; real PNG output has been validated on Windows, not asserted for other platforms. Static exports do not include camera interaction or picking.
API and options reference
Import from the package root. The bundled TypeScript declarations are the detailed option contract for 0.0.1.
createChart(canvas, options, style?)Browser chart instance with rendering, resizing, updates, interactions, events and cleanup.plot(options)Renderer-neutral scene; requires type, width and height.renderToCanvas(canvas, options, style?)Draw into a supplied canvas.renderToPNG()Existing placeholder payload contract, not general PNG export.Top-level options include type, engine, data/traces, width/height, responsive, title/subtitle, axes, subplots, viewport, legend, interactions, style and references. Add the matching family branch: bar, polar, heatmap, wonderplot, or an experimental 3D branch.
Core instance methods: render, resize, updateOptions, setData, setTraces, setTraceData, appendData, getViewport, setViewport, zoomIn, zoomOut, pan, resetZoom, autoscale, getChartState, setChartState, on, off, and destroy. Family-specific rotation/camera and tooltip/crosshair/selection methods are also exposed.
Troubleshooting
engine: "ts" to isolate optional runtime loading.auto for supported fallback or ts for a known TypeScript path.x/y; heatmaps need x/y/value.destroy() on unmount. Avoid bidirectional state event loops.Experimental 3D scenes
scatter3d and line3d accept finite numeric { x, y, z } points. Scatter points may also carry value, size and opacity. surface uses a regular point grid; mesh3d joins vertices with explicit triangular face indices. Camera and scene options may change in a future minor release.
createChart(canvas, {
type: "scatter3d", engine: "ts",
data: [
{ x: -1, y: 0, z: 0, value: 10 },
{ x: -0.5, y: 0.4, z: 0.7, value: 25 },
{ x: 0, y: 1, z: 1, value: 40 },
{ x: 0.5, y: 0.6, z: -0.4, value: 60 },
{ x: 1, y: 0, z: -1, value: 80 },
],
scene3d: {
renderer: "canvas",
camera: { projection: "perspective", eye: [1.9, 1.45, 1.9], fieldOfViewDegrees: 30 },
xAxis: { title: "X" }, yAxis: { title: "Y" }, zAxis: { title: "Z" },
},
scatter3d: {
colorScale: { lowColor: "#2563eb", highColor: "#ef4444" },
},
interactions: { camera3d: true, tooltip: true },
});
Line3D
Line3D connects ordered 3D points. Its family options include line width, opacity and linear or smooth interpolation.
createChart(canvas, {
type: "line3d", engine: "ts",
data: [
{ x: -1, y: 0, z: 0 },
{ x: -0.5, y: 0.6, z: 0.5 },
{ x: 0, y: 1, z: 1 },
{ x: 0.5, y: 0.7, z: 0.5 },
{ x: 1, y: 0, z: 0 },
],
scene3d: { renderer: "canvas",
camera: { projection: "perspective", eye: [1.9, 1.45, 1.9], fieldOfViewDegrees: 30 } },
line3d: { lineWidth: 3, lineOpacity: 0.85,
interpolation: "smooth" },
});
Surface
Surface builds triangles from a regular x/y grid of height samples. Keep the grid complete and ordered; wireframe and contour options make shape changes easier to inspect.
createChart(canvas, {
type: "surface", engine: "ts",
data: [
{ x: 0, y: 0, z: 0 }, { x: 1, y: 0, z: 0.3 }, { x: 2, y: 0, z: 0 },
{ x: 0, y: 1, z: 0.3 }, { x: 1, y: 1, z: 1 }, { x: 2, y: 1, z: 0.3 },
{ x: 0, y: 2, z: 0 }, { x: 1, y: 2, z: 0.3 }, { x: 2, y: 2, z: 0 },
],
scene3d: { renderer: "canvas",
camera: { projection: "perspective", eye: [1.9, 1.45, 1.9], fieldOfViewDegrees: 30 } },
surface: {
lowColor: "#0ea5e9", highColor: "#f97316",
wireframe: { color: "#0f172a", width: 1, opacity: 0.4 },
},
});
Mesh3D
A mesh indexes explicit triangular faces into its vertex array. Face colors, opacity, wireframe, lighting and optional culling control its appearance.
createChart(canvas, {
type: "mesh3d", engine: "ts",
data: [
{ x: 0, y: 0, z: 0 }, { x: 1, y: 0, z: 0 },
{ x: 1, y: 1, z: 0 }, { x: 0, y: 1, z: 0 },
],
scene3d: { renderer: "canvas",
camera: { projection: "perspective", eye: [1.9, 1.45, 1.9], fieldOfViewDegrees: 30 } },
mesh3d: {
faces: [[0, 1, 2], [0, 2, 3]],
faceColors: ["#2563eb", "#14b8a6"],
wireframe: { color: "#0f172a", width: 1, opacity: 0.8 },
},
});
Scatter and line offer bounded level-of-detail options. Canvas and WebGL2 renderer selection is capability-dependent. These families use the TypeScript scene path for auto or ts; strict rust fails explicitly.
Release status
fastplotjs@0.0.1 is the initial pre-1.0 npm release. The package ships compiled distribution files and declarations; the project repository remains private. Experimental 3D is identified separately, and not every chart family has a Rust builder.
Install from the public npm package. The package is marked UNLICENSED; publication does not itself grant use or redistribution rights beyond applicable law or a separate agreement. Documentation snippets show public configuration only.
