Skip to main content

Overlays

Overlays are an optional SVG layer that sits above nodes and edges. Use them for signals, annotations, selection indicators, grid labels, and other transient visual elements.

Mental model

An overlay has two halves:

  • Authoring: use builder.overlay((o) => ...) to describe what overlays exist and with what params
  • Rendering: the overlay registry turns each spec into SVG (built-ins ship pre-registered; custom visuals need a registered renderer)

Built-in primitive overlays

Three primitives work out of the box without a custom renderer: rect, circle, and text.

Primitive overlays can also anchor themselves to a node center with nodeId. circle and text use the resolved node center directly, rect centers itself on that anchor, and group uses it as the group origin. When nodeId is omitted, VizCraft keeps the existing absolute x / y behavior.

Signal overlay

The built-in signal overlay draws a moving marker between two nodes. By default it interpolates between node centers:

Follow the rendered edge path

Signals follow the rendered edge path by default: when an edge connects from -> to (in either direction — reverse hops sample the path backwards), the dot travels along its actual geometry, including waypoints, curves, and orthogonal/boundary routing. With multiple parallel edges the first declared one wins; pass edgeId to pick a specific edge. Set followEdge: false to force straight center-to-center interpolation, which is also the fallback when no edge exists between the nodes.

Keep a signal parked after arrival

Set resting: true to keep the same signal overlay visible at to once progress >= 1. Use parkAt to override the parked node and parkOffsetX / parkOffsetY to stack multiple arrived signals without switching to a different overlay kind. See SignalOverlayParams for the exported type.

Animate a declarative multi-hop signal chain

Use chain to describe multiple hops inside one signal overlay. floor(progress) selects the active hop and the fractional part is that hop's local progress. Once progress >= chain.length, VizCraft parks the signal at the final hop's to node automatically. Each hop follows its matching edge path by default; set followEdge: false on a hop to opt out, or edgeId to pin a specific edge.

Color individual signal balls

Set color to override the default blue fill on a per-signal basis. An optional glowColor adds a drop-shadow halo around the ball (defaults to color when omitted). When neither field is set, the signal uses the CSS class default (#3b82f6).

Combining multiple overlays

Use the callback form to compose several overlays in one call:

Built-in overlay kinds

These ship in the default registry and can be used immediately:

KindDescription
signalMoving marker between nodes, across hop chains, along edge paths, or parked in a node
grid-labelsAxis/grid labels for the grid system
data-pointsPoints attached to nodes
rectPrimitive rectangle (via .rect() helper)
circlePrimitive circle (via .circle() helper)
textPrimitive text label (via .text() helper)
groupPrimitive overlay container with local child coordinates (via .group() helper)

Keys

Overlays reconcile by unique key:

  • If spec.key is present, that's used
  • Otherwise, spec.id is used

If you render multiple overlays with the same id, always provide a key. The callback builder auto-generates stable keys for unkeyed overlays of the same id.

Animating overlays

Overlay params can be targeted by the data-only timeline animation system. Give the overlay instance a stable key and target it in animations with aBuilder.overlay('key'):

Group overlays

Move multiple overlay elements as one unit using a group overlay:

Set nodeId with optional offsetX / offsetY when the group's local origin should stay attached to a node center instead of an absolute scene position.

Registering custom overlay kinds

When built-in kinds aren't enough, register a new renderer:

import { defaultCoreOverlayRegistry } from 'vizcraft';

defaultCoreOverlayRegistry.register('selection', {
render: ({ spec }) => {
const { x, y, w, h } = spec.params;
return `<rect x="${x}" y="${y}" width="${w}" height="${h}" rx="8" class="viz-selection" />`;
},
update: ({ spec }, g) => {
let rect = g.querySelector('rect');
if (!rect) {
rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
g.appendChild(rect);
}
rect.setAttribute('x', String(spec.params.x));
rect.setAttribute('y', String(spec.params.y));
rect.setAttribute('width', String(spec.params.w));
rect.setAttribute('height', String(spec.params.h));
rect.setAttribute('rx', '8');
rect.setAttribute('class', spec.className ?? 'viz-selection');
},
});

// Use it
builder.overlay('selection', { x: 10, y: 10, w: 200, h: 120 }, 'sel');
note

The default registry is a singleton. Register custom overlays once (idempotently).

For the complete overlay builder API, see the Overlay API Reference.


Found a problem? Open an issue on GitHub.