verve.viz
Guide: Visualization · live: example, multi-instance, canvas, canvas multi-instance.
Graphs
| Export | Notes |
|---|---|
Graph | { nodes: []GraphNode, edges: []GraphEdge, layout } |
GraphNode | { id, label, … } · GraphEdge { from, to } |
Layout | .force .tree .radial .dag |
GraphOpts | width/height, node/edge/label colors, margin, edge_routing (.straight/.curved/.orthogonal), dag_crossing_iterations |
renderGraph(ctx, g, opts) | static SSR SVG |
renderGraphInteractive(ctx, g, opts) | interaction-annotated SVG (pair with VizGraphInteractive island) |
graphPositions(ctx, g, opts) | computed positions for props hand-off |
edgePathD(alloc, points, routing, opts) | edge path d string (plugs into anim motionPath) |
Charts
barChart stackedBarChart groupedBarChart lineChart areaChart scatterChart pieChart (donut via inner_ratio) candlestickChart boxPlotChart heatmapChart radarChart violinChart sankeyChart treemapChart chordChart — all (ctx, data, ChartOpts) *Node.
Data types: Datum{ label, value }, Point{ x, y }, Candle{ label, open, high, low, close }, BoxStats{ label, min, q1, median, q3, max }, StackSeries{ name,
values, color }, ViolinSeries{ label, samples }, SankeyNode/SankeyLink, TreemapItem{ label, value, parent }.
Scales & scene
LinearScale BandScale LogScale TimeScale Axis Vec2 Rect Scene Shape Style — public for custom SVG scenes.
Live deltas
| Export | Signature |
|---|---|
diffGraphs | (alloc, old_nodes, old_edges, new_nodes, new_edges) ![]DeltaOp |
writeDeltaJson | (buf, seq, ops) ![]const u8 — {"seq":N,"ops":[…]} |
applyDeltaOps | apply ops to a mutable graph |
Clients apply a delta only when seq is exactly one past their last snapshot; gaps trigger a pull resync (vizGraph snapshot action pattern).
Interactive islands — multi-instance
VizGraphInteractive and VizGraphCanvas each hold a fixed [MAX_INSTANCES]Inst slot pool (MAX_INSTANCES = 2 in both islands). findSlot(vid) / allocSlot(vid) map a data-vid (the SSR-assigned island instance id — see verve.island's IslandOpts.id / auto-sequential assignment) to its Inst; hydrate's root_id argument is that vid. Every subsequent bridge-dispatched export (pointer/wheel/drag handlers, vizcanvas_select(root_id) before a frame or event dispatch) re-selects the instance for the vid in play, so state — zoom/pan, drag, hover, selection, collapse — never leaks between co-resident instances. A page with one instance simply uses one slot; behavior is unchanged from the single-instance island.
islands.VizGraphInteractive.Props (positionally mirrored in the chunk): xs: []f64, ys: []f64, ef: []u32, et: []u32 (edge endpoint node indices), labels: [][]u8, ids: [][]u8, layout: u32 (@intFromEnum(Layout)), margin: f64, edge_routing: u32 (@intFromEnum(edge_path.Routing): 0=straight, 1=curved, 2=orthogonal). edge_routing drives both the initial SSR edge shape and live re-route on node drag (chunk rebuilds the affected edge's d from edge_path.pathDBuf on every viz_pointermove while dragging, for non-straight routings).
VizGraphCanvas takes no props — its demo graph (GRAPH_N = 1500 nodes, capped at MAX_N = 4096 per instance) is synthesized client-side (deterministic jittered grid, index-seeded) since the SSR props scratch can't carry a graph that size. It renders via core/viz/canvas_buf into one packed draw buffer per frame (header + node + edge arrays) and calls the bridge's canvas2d batched-draw path — one draw call per frame instead of one SVG element per node/edge. Pan/zoom/hover/select are hit-tested against the current view transform (vizcanvas_pointerdown/pointermove/pointerup/wheel), not per-element DOM events.