Documentation

transition()

Create one seekable transition between two states of the same chart type.

import { transition } from 'visdelta/transition';

function transition(
  from: Visualization,
  to: Visualization,
  options: TransitionOptions,
): Promise<VisualizationTransition>;

transition() resolves and loads both states' data, computes their delta(), loads the chart's renderer and mounts a seekable route into options.target. If setup fails, the target's previous contents are restored.

const change = await transition(from, to, {
  target: '#chart',
  data: { sales: rows },
  height: 420,
  chartStyle: paperChartStyle,
});

from and to can be builder states or plain specs; plain specs need a registered chart module.

TransitionOptions

Prop

Type

Canvas size

width and height are the outer size of the canvas (the SVG), margins included, as in Observable Plot. Each takes a number of CSS pixels or "auto".

OptionOmittedA number"auto"
widthThe container's width, inside the figure's own border, re-fit on change.Exactly this wide. A narrower container overflows; nothing is clipped.Exactly the container's content width, re-fit when it changes.
heightThe chart's own height (an authored height, else 500).Exactly this tall; overrides the chart's own height.Exactly the container's content height, re-fit when it changes. The container needs a height of its own.
// Fixed: always 640 × 360, whatever the container is.
await transition(from, to, { target: '#chart', width: 640, height: 360 });

// Fit: follow the container, e.g. a resizable or floating panel with a height.
await transition(from, to, { target: '#panel', width: 'auto', height: 'auto' });

A chart is wrapped in a figure that a theme may give a border. A number is always the canvas itself, so that chrome sits outside it. A top legend also sits outside the canvas, above it, and never counts toward width or height. For "auto" the figure's border on that axis gives way and the legend takes its room from the container, so the canvas fills exactly what is left and nothing overflows the container. The legend is a second <svg class="vd-legend-svg"> that exists only while there is a legend, after the canvas in the document, so querySelector('svg') is still the canvas. A transition opens or closes the legend space with playback progress. In Fit mode the canvas uses the remaining height. A style with legendPosition: 'right' keeps its legend inside the canvas.

height: 'auto' reads the room the container gives the chart. A container with no height of its own (its height comes from its content) gives none, so the chart keeps its own height instead of growing in a loop. Give the container a fixed height, or make it a flex or grid track. An explicit height also releases the view's default min-height, so it is the canvas height rather than a floor under it.

target is a CSS selector or an element. The transition owns its contents until destroy().

VisualizationTransition

The returned controller.

Prop

Type

MethodReturnsNotes
progress(value)controllerPauses playback and draws one frame. Finite values clamp to [0, 1].
play(options?)controllerAnimates from from to to; see PlayOptions.
pause()controllerStops playback at the current frame.
resize(options?)controllerRecompiles at the container's size and current theme, keeping progress. { width, height } change the requested canvas size; a dimension left out keeps its request.
stageCount()numberSerial route stages VisDelta planned for the pair (at least 1). They split progress equally, and play({ duration }) gives each stage duration ms, so a full play lasts stageCount() × duration.
destroy()voidStops playback, disconnects observers and removes the chart.

Pair controllers observe their container's width and resize automatically.

PlayOptions

Prop

Type

change.play();                       // 0 → 1
change.play({ from: 1, to: 0 });     // reverse
change.play({ from: change.value });  // resume

Errors

MessageCause
transition() requires two states of the same chart type.Endpoints from different chart families
VisDelta needs a target: …options.target is missing
VisDelta target not found: …The selector matched no element
transition(): missing dataset "…"A named source is not in options.data
progress must be a finite number.progress() received NaN or Infinity
duration must be a finite non-negative number.Invalid play({ duration })
This transition has been destroyed.The controller was used after destroy()

See Troubleshooting for fixes.

Inspect compiled motion

await change.inspect() returns the compiled SVG phases and their recorded property tracks, without pausing playback or changing its position. Each phase has normalized start, end, and properties; each property identifies its DOM node, name, kind, scheduled interval within the phase, and from / to values at the phase boundaries. These are not necessarily the endpoints of a delayed or chained property interval.

await sequence.inspect() reads the active leg. Refresh after resize or theme changes. Borrowed nodes must not be mutated; reconstruction, resize and destroy invalidate them. Custom tweens are explicitly opaque. Immediate DOM writes and insertions/removals are outside this recorded SVG report. The playground's Inspect stages control displays these tracks alongside the timeline, including the coverage limits.

When height is "auto" (Fit), a constrained container hides the legend to preserve the main canvas. The canvas budget is half the available width, capped at 200 pixels. The legend returns when space allows; fixed pixel heights retain it.

change.stageChanges() reports the semantic changes between each actual pair of planned intermediate states, in authored playback order. The playground uses these to label the stage strip directly. It does not split the full pair's delta into guessed phases.

transition.stageOperations() returns the exact planner operation for each route stage, in authored playback order. Each entry carries the slot path, action, and previous/next declaration values. Direct and chart-refined stages return undefined; semantic categories remain available through stageChanges(). These operations do not prove visible motion or alter stage timing.

Each inspected property includes ancestry, an array of { tag, classes } from its SVG root to the animated element. It is captured with the phase DOM restored, before seeking can detach entering or exiting nodes. This snapshot remains readable after inspection restores the visible frame. Repeated elements can share an ancestry; selector retains the phase-specific positional path. An empty ancestry means no complete SVG path was available.

On this page