path-rite

sankeyLayout

Compute a Sankey diagram layout with positioned nodes and routed links.

sankeyLayout(nodes: SankeyNode[], links: SankeyLink[], config: SankeyConfig): SankeyResult

nodes — Array of node definitions:

  • id: string — Unique identifier for the node.
  • label?: string — Display label. Defaults to id if omitted.

links — Array of link definitions:

  • source: string — ID of the source node.
  • target: string — ID of the target node.
  • value: number — Flow magnitude through this link.

config — Layout configuration:

  • extent: [[x0, y0], [x1, y1]] — Bounding rectangle for the layout.
  • nodeWidth?: number — Width of each node rectangle. Default: 24.
  • nodePadding?: number — Vertical spacing between nodes in the same column. Default: 8.
  • iterations?: number — Number of relaxation passes for position refinement. Default: 6.

Returns — A SankeyResult with positioned nodes and links:

result.nodes — Array of positioned nodes:

  • id: string — Node identifier.
  • label: string — Display label.
  • x0, y0, x1, y1: number — Bounding rectangle coordinates.
  • value: number — Node value (max of total incoming, total outgoing).
  • depth: number — Column index (0 = leftmost).

result.links — Array of positioned links:

  • source: string — Source node ID.
  • target: string — Target node ID.
  • value: number — Flow magnitude.
  • width: number — Visual width of the link band.
  • y0: number — Center y-position at the source node.
  • y1: number — Center y-position at the target node.
  • sourceX: number — X-coordinate of the source end (right edge of source node).
  • targetX: number — X-coordinate of the target end (left edge of target node).
const nodes = [
  { id: "A" },
  { id: "B", label: "Category B" },
  { id: "C" },
  { id: "D" },
];
const links = [
  { source: "A", target: "B", value: 30 },
  { source: "A", target: "C", value: 20 },
  { source: "B", target: "D", value: 25 },
  { source: "C", target: "D", value: 15 },
];
const layout = pathRite.sankeyLayout(nodes, links, {
  extent: [[0, 0], [600, 400]],
  nodeWidth: 20,
  nodePadding: 10,
});

// Render nodes as rectangles
layout.nodes.forEach(n => {
  // rect at (n.x0, n.y0) with size (n.x1-n.x0, n.y1-n.y0)
});

// Render links as curved bands
layout.links.forEach(l => {
  // Cubic bezier from (l.sourceX, l.y0) to (l.targetX, l.y1) with width l.width
});