Sankey Chart
The Sankey Chart routes weighted flows between nodes as links whose width is proportional to the value carried, so where a quantity splits and merges is visible without reading a single number. Reach for it for energy and material flows, budget allocation, process pipelines and user journeys. Nodes are placed automatically by a layered layout: iterations sets how many relaxation passes it makes, and nodeWidth and nodePadding size the columns. Hover a link to highlight it, and legend and format handle the annotation. Renders to Canvas, SVG or a terminal context.
NOTE
For the full API, see the Charts API Reference.
Example
Usage
import {
createSankeyChart,
} from '@ripl/charts';
const chart = createSankeyChart('#container', {
nodes: [
{
id: 'a',
label: 'Source A',
},
{
id: 'b',
label: 'Target B',
},
],
links: [
{
source: 'a',
target: 'b',
value: 100,
},
],
});Data Format
A sankey chart takes nodes and the links between them. A link's source and target are node ids, and its value sets the ribbon's thickness:
const nodes = [
{
id: 'search',
label: 'Search',
},
{
id: 'signup',
label: 'Sign up',
},
{
id: 'purchase',
label: 'Purchase',
},
];
const links = [
{
source: 'search',
target: 'signup',
value: 620,
},
{
source: 'signup',
target: 'purchase',
value: 180,
},
];Node depth is computed from the link graph, so nodes do not need to be ordered.
Options
A full configuration for this chart. The options every chart shares — padding, title, animation, theme and the rest — behave the same everywhere and are documented on Shared Options.
createSankeyChart('#container', {
nodes,
links,
// Width of each node rectangle, in pixels.
nodeWidth: 20,
// Vertical gap between stacked nodes in a column, in pixels.
nodePadding: 10,
// Layout relaxation passes. Accepted and reserved for tuning node positioning — the current
// layout does not read it, so changing it has no visible effect yet.
iterations: 6,
legend: { position: 'bottom' },
format: 'number',
});Events
Subscribe with chart.on(...). A handler receives an Event object, not the payload directly — the payload is on event.data, and carries the interacted datum plus its { x, y } anchor in chart pixels. event.target and event.stopPropagation() are also available.
// Emitted when a node is clicked.
chart.on('nodeclick', event => console.log(event.data)); // event.data: SankeyChartNodeEvent<TData>
// Emitted when the pointer enters a node.
chart.on('nodeenter', event => console.log(event.data)); // event.data: SankeyChartNodeEvent<TData>
// Emitted when the pointer leaves a node.
chart.on('nodeleave', event => console.log(event.data)); // event.data: SankeyChartNodeEvent<TData>
// Emitted when a link is clicked.
chart.on('linkclick', event => console.log(event.data)); // event.data: SankeyChartLinkEvent
// Emitted when the pointer enters a link.
chart.on('linkenter', event => console.log(event.data)); // event.data: SankeyChartLinkEvent
// Emitted when the pointer leaves a link.
chart.on('linkleave', event => console.log(event.data)); // event.data: SankeyChartLinkEvent