Documentation

Line

Ordered trends with keyed observations inside the path and honest gaps by default.

import { line } from 'visdelta/line';

line() shows an ordered trend. .key() identifies observations inside the SVG path, not only as separate point elements, so a single observation can enter or leave a line.

Preparing transition
0.00
line-split.ts
import { line } from 'visdelta/line';
import { transition } from 'visdelta/transition';
import 'visdelta/style.css';

const prices = [
  { date: '2026-01-05', ticker: 'NOVA', close: 41 },
  { date: '2026-01-12', ticker: 'NOVA', close: 44 },
  { date: '2026-01-19', ticker: 'NOVA', close: 43 },
  { date: '2026-01-26', ticker: 'NOVA', close: 48 },
  { date: '2026-02-02', ticker: 'NOVA', close: 52 },
  { date: '2026-02-09', ticker: 'NOVA', close: 50 },
  { date: '2026-01-05', ticker: 'ORBIT', close: 33 },
  { date: '2026-01-12', ticker: 'ORBIT', close: 31 },
  { date: '2026-01-19', ticker: 'ORBIT', close: 35 },
  { date: '2026-01-26', ticker: 'ORBIT', close: 34 },
  { date: '2026-02-02', ticker: 'ORBIT', close: 30 },
  { date: '2026-02-09', ticker: 'ORBIT', close: 36 },
];

const detailed = line(prices)
  .x('date', { type: 'temporal', label: 'Week' })
  .y('close', { label: 'Close (USD)' })
  .key(['date', 'ticker'])
  .breakdown('ticker')
  .color('ticker');

// One mean line splits into one line per ticker.
const from = detailed.rollup({ op: 'mean' });
const to = detailed;

const change = await transition(from, to, { target: '#chart' });
change.play({ duration: 800 }); // or change.progress(0.5)

Methods

MethodMeaning
.curve(d3CurveName)Use any exact D3 line-curve export
.connect('adjacent' | 'across')Keep honest gaps, or connect across them
.strokeWidth(number)Set the line width
.pointSize(number)Set the point radius
.flip(options?)Swap the position mappings in an explicit order
.breakdown(field, options?)Split one line into series
.rollup(options?)Combine series into one line

Curve names are exact D3 exports such as curveLinear, curveStep and curveMonotoneX. Line also accepts curveBundle. The full list is exported as D3_CURVE_NAMES.

const prices = line(rows)
  .x('date', { type: 'temporal' })
  .y('close')
  .key(['date', 'ticker'])
  .breakdown('ticker')
  .color('ticker');

const average = prices.rollup({ op: 'mean' });

Transition behaviour

  • Adding an observation extends the line to it before its point appears.
  • Removing or filtering runs the same frames backward: the point leaves before the segment retracts.
  • Gaps stay honest. With the default connect('adjacent'), filtered observations leave a visible gap. connect('across') joins across them.
  • Split and merge zip series out of, and back into, the summary line.
Preparing transition
0.00

Limits

The declaration planner treats raw y remapping as an Encoding operation and a supported summary (source field, reducer and output alias) as one Grain operation. Raw-to-summary pairs keep Line's native route when eligible. Complex pipelines remain outside the planner and use the ordinary transition.

Try it

Edit an average line that unzips into AAPL and GOOG in the playground.

On this page