createChart
Creates a new Velo Plot instance.
Signature
function createChart(options: ChartOptions): ChartOptions
| Property | Type | Default | Description |
|---|---|---|---|
container | HTMLElement | required | Container element for the chart |
id | string | auto-generated | Stable chart id for sync groups (chart.getId()) |
renderer | 'webgl' | 'webgpu' | 'svg' | 'webgl' | Chart renderer backend (see Renderer backend) |
xAxis | AxisOptions | { auto: true } | X-axis configuration |
yAxis | AxisOptions | { auto: true } | Y-axis configuration |
theme | string | ChartTheme | 'dark' | Theme name or custom theme object |
background | string | Theme default | Background color |
showControls | boolean | false | Show toolbar controls |
showLegend | boolean | true (theme) | Show series legend — defaults to theme.legend.visible |
showStatistics | boolean | false | Enable stats panel (requires StatsPlugin) |
devicePixelRatio | number | window.devicePixelRatio | Pixel ratio for rendering |
loading | boolean | LoadingConfig | false (implicit) | Show loading indicator — opt-in in v3 core |
animations | boolean | AnimationConfig | true | Enable navigation animations |
responsive | boolean | ResponsiveConfig | true | Auto-resize on container change |
layout | LayoutOptions | defaults | Control margins and axis title spacing |
Bundle entry
Series types and chart methods depend on which entry you import. Core supports line/scatter/step/band/area; candlestick and trading APIs require velo-plot/trading. See Bundle Architecture and Trading Bundle.
Modular Architecture
From version 1.5.0, Velo Plot uses a modular plugin architecture. Advanced features (tooltips, analysis, annotations) must be loaded with chart.use(). In v3, bundle entry also determines built-in series and trading methods.
AxisOptions
interface AxisOptions {
scale?: 'linear' | 'log' // Scale type
label?: string // Axis label
auto?: boolean // Auto-scale to fit data
min?: number // Fixed minimum (if auto=false)
max?: number // Fixed maximum (if auto=false)
invertAxis?: boolean // Render the axis in descending order
}Inverted Axes
Set invertAxis: true when a domain conventionally reads high-to-low. The data arrays stay in their natural order, but the rendered axis direction and interaction coordinates are reversed.
const chart = createChart({
container: document.getElementById('chart'),
xAxis: {
label: 'Wavenumber (cm^-1)',
auto: true,
invertAxis: true,
},
yAxis: {
label: 'Transmittance (%)',
auto: true,
},
})Axis Label Spacing
Adjust the distance between the axis label and the plot border with layout settings:
const chart = createChart({
container: document.getElementById('chart'),
layout: {
xAxisLayout: { titleGap: 48 },
yAxisLayout: { titleGap: 24 },
},
})xAxisLayout.titleGap moves the X-axis label vertically. yAxisLayout.titleGap moves Y-axis labels horizontally.
By default, the X-axis label gap is 45 and the Y-axis label gap is 50.
Renderer backend
Velo Plot renders series with WebGL2 by default (NativeWebGLRenderer).
WebGPU (renderer: 'webgpu') requires an extended bundle import (velo-plot/trading, velo-plot/scientific, or velo-plot/full). On core-only imports, 'webgpu' is silently ignored — the chart stays on WebGL2.
SVG (renderer: 'svg') renders the chart as a live vector layer (same createChart API, pan/zoom, plugins, interactions). Requires an extended bundle entry so exportSVG is patched. Canvases are hidden; each frame rebuilds the SVG from the same export pipeline used by chart.exportSVG(). 3D series are not supported in SVG mode. Use showLegend: true for the interactive DOM legend (vector frame skips duplicate legend markup).
import { createChart } from 'velo-plot/trading'
const chart = createChart({
container: document.getElementById('chart')!,
renderer: 'webgl', // default — NativeWebGLRenderer
});
const webgpuChart = createChart({
container: document.getElementById('chart')!,
renderer: 'webgpu', // WebGPU when available, else WebGL2 fallback
});
const svgChart = createChart({
container: document.getElementById('chart')!,
renderer: 'svg', // live vector — extended bundle only
});
console.log(webgpuChart.getActiveRenderer()); // 'webgpu' | 'webgl'
console.log(svgChart.getActiveRenderer()); // 'svg'| Value | Behavior |
|---|---|
'webgl' | Native WebGL2 renderer (default). All series types for your bundle entry. |
'webgpu' | GpuChartRenderer when extended entry loaded. WebGL2 fallback if unavailable (ADR 001). |
'svg' | Live SVG vector renderer. Same chart API; no WebGL draw path. Extended bundle required. No 3D. |
For WebGPU compute experiments (not chart rendering), use PluginGpu from velo-plot/plugins/gpu.
Returns
Returns a Chart instance with the following methods:
Series Management
chart.addSeries({
id: 'my-series',
type: 'line', // 'line' | 'scatter' | 'line+scatter' | 'step' | 'area' | 'band' (+ extended types per bundle)
data: { x, y }, // Float32Array or Float64Array
style: { color: '#00f2ff', width: 2 },
})
// Update series data
chart.updateSeries('my-series', { x: newX, y: newY })
// Append data to existing series
chart.updateSeries('my-series', { x: newX, y: newY, append: true })
// Remove a series
chart.removeSeries('my-series')
// Get a series
const series = chart.getSeries('my-series')
// Get all series
const allSeries = chart.getAllSeries()View Control
// Zoom to specific bounds
chart.zoom({ x: [0, 100], y: [-1, 1] })
// Pan by pixel delta
chart.pan(50, 0) // Pan right 50px
// Safe fit — no-op when series have no valid bounds
chart.fit({ padding: { x: 0.02, y: 0.05 } })
chart.fit({ x: [t0, t1], y: [0, 100] })
// Reset to fit from data (calls fit(), not blind autoScale)
chart.resetZoom()
// Force auto-scale (legacy; prefer fit() for empty-safe behavior)
chart.autoScale()
// Stable id for ChartGroup / createMasterSlave
chart.getId()
// Current device pixel ratio
chart.getDPR()
chart.setDPR(window.devicePixelRatio)
// { xMin: 0, xMax: 100, yMin: -1, yMax: 1 }
// NOTE: autoScale() uses 0.5% padding. fit() uses 2% X / 5% Y padding by default.fit()
Safe alternative to autoScale() that skips empty series:
interface FitOptions {
x?: [number, number] // explicit X range
y?: [number, number] // explicit Y range (primary axis)
padding?: number | { x?: number; y?: number } // default 2% X, 5% Y
animate?: boolean
}
chart.fit() // fit from visible series
chart.fit({ x: [0, 1e6] }) // lock X, auto Y
chart.resetZoom() // equivalent to chart.fit()Sharp rendering (HiDPI)
Charts can look blurry on Retina displays when canvas backing-store pixels are fractional. Velo Plot:
- Rounds canvas dimensions to integer device pixels
- Uses
setTransform(dpr, …)instead of cumulativescale() - Re-reads
window.devicePixelRatioon each resize (unlessdevicePixelRatiois fixed in options)
const chart = createChart({
container,
devicePixelRatio: window.devicePixelRatio, // recommended on HiDPI
})Loading State
The loading overlay is opt-in in v3 core — pass loading: true in createChart options. Until the loading plugin is loaded, chart.loading is a no-op stub.
const chart = createChart({
container,
loading: true, // required in v3 core to show overlay
})
// Show with custom message
chart.loading.show("Processing large dataset...")
// Update progress (0-100)
chart.loading.setProgress(45)
// Hide manually
chart.loading.hide()Cursor
// Enable crosshair cursor
chart.enableCursor({
snap: true, // Snap to nearest data point
crosshair: true, // Show crosshair lines
formatter: (x, y) => `X: ${x.toFixed(2)}\nY: ${y.toFixed(2)}`,
})
// Disable cursor
chart.disableCursor()Events
// Listen to render events (for FPS monitoring)
chart.on('render', ({ fps, frameTime }) => {
console.log(`${fps} FPS, ${frameTime}ms per frame`)
})
// Listen to zoom events
chart.on('zoom', ({ x, y }) => {
console.log(`View: X[${x[0]}, ${x[1]}], Y[${y[0]}, ${y[1]}]`)
})
// Listen to pan events
chart.on('pan', ({ deltaX, deltaY }) => {
console.log(`Panned: ${deltaX}, ${deltaY}`)
})
// Remove listener
chart.off('render', handler)Lifecycle
// Manually resize (usually automatic via ResizeObserver)
chart.resize(800, 600)
// Force a render
chart.render()
// Export as image (built-in raster — available on core)
const dataUrl = chart.exportImage('png') // or 'jpeg'
// Export as SVG string (vector) — requires extended bundle
// import from 'velo-plot/trading', 'velo-plot/scientific', or 'velo-plot/full'
const svg = chart.exportSVG() // throws on core-only import
// High-res / WebP / SVG download via plugin:
// chart.use(PluginSnapshot())
// await chart.snapshot.downloadSnapshot({ format: 'svg' })
// Use a plugin
chart.use(myPlugin)
// Clean up when done
chart.destroy()Example
import { createChart } from 'velo-plot'
// Create chart
const chart = createChart({
container: document.getElementById('chart'),
xAxis: { label: 'Time (s)', auto: true },
yAxis: { label: 'Amplitude', auto: true },
theme: 'midnight',
showControls: true,
showLegend: true,
})
// Generate data
const n = 10000
const x = new Float32Array(n)
const y = new Float32Array(n)
for (let i = 0; i < n; i++) {
x[i] = i / 100
y[i] = Math.sin(x[i]) + Math.random() * 0.1
}
// Add series
chart.addSeries({
id: 'signal',
type: 'line',
data: { x, y },
style: { color: '#00f2ff', width: 1.5 },
})
// Enable cursor with custom formatting
chart.enableCursor({
snap: true,
crosshair: true,
formatter: (xVal, yVal) =>
`Time: ${xVal.toFixed(2)}s\nValue: ${yVal.toFixed(4)}`,
})
// Monitor performance
chart.on('render', ({ fps }) => {
document.getElementById('fps').textContent = `${fps} FPS`
})Themes
Built-in themes: 'dark', 'light', 'midnight', 'electrochemistry'
// Use built-in theme
const chart = createChart({
container,
theme: 'midnight',
})
// Use custom theme
import { createTheme } from 'velo-plot'
const myTheme = createTheme({
name: 'custom',
backgroundColor: '#1a1a2e',
gridColor: 'rgba(255,255,255,0.1)',
axisColor: '#888',
// ... more options
})
const chart = createChart({
container,
theme: myTheme,
})Known limitations
- Series types and
renderer: 'webgpu'depend on bundle entry — see Bundle Architecture. - Polar, gauge, and sankey series render on the Canvas 2D path when WebGPU is selected — they fall back to WebGL/Canvas automatically.
- Default
loadingis off in v3 core — passloading: truefor the init overlay.