Core Concepts
Understanding the architecture of Velo Plot.
Bundles
velo-plot ships multiple library entry points (core, trading, scientific, full). See Bundle Architecture before choosing imports.
Architecture Overview
┌─────────────────────────────────────────────────────────────┐
│ Bundle entry (import) │
│ velo-plot │ /trading │ /scientific │ /full │
│ └─ registerExtendedSeries / registerTrading │
├─────────────────────────────────────────────────────────────┤
│ Chart Instance (ChartCore) │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Series │ │ Series │ │ Series │ │
│ │ (WebGL) │ │ (WebGL) │ │ (WebGL) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────────────────┐│
│ │ WebGL Renderer (NativeWebGLRenderer) ││
│ │ • Core: line, scatter, step, band ││
│ │ • Extended: bar, heatmap, boxplot, waterfall (registry)││
│ └─────────────────────────────────────────────────────────┘│
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Overlay Renderer (2D Canvas) ││
│ │ • Axes, grid, labels, cursor, legend ││
│ │ • Gauge / Sankey (extended registry) ││
│ └─────────────────────────────────────────────────────────┘│
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Plugin Manager + chart.use() ││
│ └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘Key Components
Chart
The main orchestrator that coordinates all subsystems:
- Creates and manages the DOM structure
- Handles series lifecycle
- Coordinates rendering
- Emits events
Series
Data containers with visualization properties:
- Store data in TypedArrays
- Calculate bounds
- Define visual style (color, width, type)
WebGL Renderer
Hardware-accelerated data rendering:
- Uploads data to GPU buffers once
- Renders lines/points using shaders
- Zoom/pan updates only uniforms (no data re-upload)
Overlay Renderer
2D canvas for UI elements:
- Axes with labels and ticks
- Grid lines
- Cursor crosshair and tooltips
- Selection rectangles
Interaction Manager
Handles user input:
- Mouse wheel → zoom
- Left drag → pan
- Right drag → box zoom
- Touch gestures
Data Flow
1. User calls chart.addSeries({ data: { x, y } })
│
2. Series stores TypedArrays, calculates bounds
│
3. WebGL Renderer creates GPU buffer from data
│
4. Render loop (requestAnimationFrame):
│
├─► WebGL: Draw data with current view bounds
│
└─► Overlay: Draw axes, grid, cursor
│
5. User interaction (zoom/pan):
│
└─► Update view bounds → re-render (no data re-upload)View Bounds
The visible region of the chart is defined by Bounds:
interface Bounds {
xMin: number
xMax: number
yMin: number
yMax: number
}When you zoom or pan:
- View bounds are updated
- WebGL shader uniforms are updated
- Chart re-renders with new bounds
- Data stays in GPU memory (no re-upload)
This is why zooming is instant even with millions of points.
Auto-scaling
When auto: true is set on an axis:
- Chart calculates bounds from all series data
- Adds 5% padding
- Sets view bounds to fit all data
// Enable auto-scaling
createChart({
container,
xAxis: { auto: true }, // Auto-scale X
yAxis: { auto: true }, // Auto-scale Y
})
// Manually trigger auto-scale
chart.autoScale()Event System
Charts emit events for state changes:
// Subscribe
chart.on('zoom', handler)
chart.on('render', handler)
chart.on('pan', handler)
// Unsubscribe
chart.off('zoom', handler)Events are synchronous and fire immediately after the action.
Render Loop
Velo Plot uses requestAnimationFrame for smooth rendering:
┌─────────────────────────────────────┐
│ requestAnimationFrame │
│ ↓ │
│ ┌─────────────────────────┐ │
│ │ needsRender = true? │ │
│ └──────────┬──────────────┘ │
│ │ yes │
│ ↓ │
│ ┌─────────────────────────┐ │
│ │ render() │ │
│ │ • WebGL draw │ │
│ │ • Overlay draw │ │
│ │ • Emit 'render' event │ │
│ └─────────────────────────┘ │
│ ↓ │
│ needsRender = false │
│ ↓ │
│ next frame... │
└─────────────────────────────────────┘Rendering only happens when needed (data change, zoom, pan, resize).
Memory Management
TypedArrays
Data must be Float32Array or Float64Array:
// ✅ Correct
const x = new Float32Array([1, 2, 3])
const y = new Float32Array([4, 5, 6])
// ❌ Wrong - regular arrays
const x = [1, 2, 3] // Will cause errorsCleanup
Always destroy charts when done:
// Vanilla JS
chart.destroy()
// React - automatic via useEffect cleanup
useEffect(() => {
// setup...
return () => chart.destroy()
}, [])Next Steps
- Bundle Architecture — entry points and sizes
- Series & Data - Working with data
- Interactions - User interactions
- Performance - Optimization tips