Sankey
Basic Configuration
Sankey is a popular kind of flow diagram that visualizes flows between multiple nodes. To define a Sankey diagram you'll need to have data about its nodes and flows between them.
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
import { VisSingleContainer, VisSankey } from '@unovis/react'
function Component(props) {
const data: SankeyData = props.data
return (
<VisSingleContainer data={data}>
<VisSankey/>
</VisSingleContainer>
)
}
@Component({
templateUrl: 'template.html'
})
export class Component {
@Input data: SankeyData;
}
<vis-single-container [data]="data">
<vis-sankey></vis-sankey>
</vis-single-container>
<script lang='ts'>
import { VisSingleContainer, VisSankey } from '@unovis/svelte'
export let data: SankeyData
</script>
<VisSingleContainer {data}>
<VisSankey/>
</VisSingleContainer>
<script setup lang="ts">
import { VisSingleContainer, VisSankey } from '@unovis/vue'
const props = defineProps<{ data: SankeyData }>()
</script>
<template>
<VisSingleContainer :data="data">
<VisSankey />
</VisSingleContainer>
</template>
import { VisSingleContainer, VisSankey } from '@unovis/solid'
function Component(props) {
const data: SankeyData = () => props.data
return (
<VisSingleContainer data={data()}>
<VisSankey/>
</VisSingleContainer>
)
}
import { SingleContainer, Sankey } from '@unovis/ts'
import { data, SankeyNode, SankeyLink } from './data'
const container = new SingleContainer<SankeyNode, SankeyLink>(node, {
component: new Sankey<SankeyNode, SankeyLink>({ })
}, data)
Specifically, Sankey accepts data in the following form:
type SankeyData<NodeDatum, LinkDatum> = {
nodes: NodeDatum[];
links: LinkDatum[];
}
Links
The minimal configuration for a Link datum contains source and target properties, which
correspond to the starting and ending nodes of the link, and a numerical value.
type SankeyLink = {
source: string | number | SankeyNode;
target: string | number | SankeyNode;
value?: number;
}
Note that the value is not required, but recommended since by default Sankey will use
this property to calculate the width of each link. Alternatively, you can provide a numeric accessor function
to the linkValue property.
Nodes
While there are no explicitly required properties for NodeDatum, a common configuration looks like:
type SankeyNode = {
id: string;
color: string;
label: string;
}
Alternatively, you can provide accessor functions to id, nodeColor, nodeLabel properties
to achieve the same effect.
Component Sizing
Sankey supports three different sizing options that can be set via SingleContainer: Sizing.Fit (default),
Sizing.Extend and Sizing.FitWidth.
By default, SingleContainer and Sankey will take all the available space of its parent HTML element. However, if you
set SingleContainer's sizing to Sizing.Extend (or "extend"), the diagram will be able to go beyond its parent
size and become scrollable. In that case you'll be able to control the diagram size by using the following properties:
nodeWidth, nodeHorizontalSpacing, nodeMinHeight, nodeMaxHeight, and nodePadding (see
Node Sizing).
The Sizing.FitWidth (or "fit_width") option is similar to the Sizing.Extend option, but the whole component will be scaled down
proportionally to fit horizontally into its container; vertical scrolling will remain available.
Interactive Zoom and Pan
Zooming scales the Sankey layout (not individual SVG elements), preserving stroke widths and label sizes. Mouse wheel zoom and drag panning are supported.
When XY zoom mode is used, holding ⌘/Ctrl key will temporarily make zoom horizontal-only and holding Alt will temporarily make it vertical-only. Setting disableZoomModifierKeys to true disabled this behavior.
- enableZoom: toggle interaction (default:
false). - zoomMode:
SankeyZoomMode.XY | SankeyZoomMode.X | SankeyZoomMode.Y(default:SankeyZoomMode.Y). - zoomExtent: allowed zoom range
[min, max](default:[1, 5]). - zoomScale:
[horizontal, vertical]layout scale factors (programmatic control). - zoomPan:
[x, y]pixel offsets (programmatic control). - onZoom: callback
(hScale, vScale, panX, panY, extent, event) => void. - disableZoomModifierKeys: prevents ⌘/Ctrl and Alt modifiers from affecting effective zoom mode (default:
false).
Smart pan constraints prevent panning beyond diagram bounds.
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisSankey label="Enable Zoom / Pan" enableZoom={true}/>
<vis-sankey label="Enable Zoom / Pan" [enableZoom]="true"></vis-sankey>
<VisSankey label="Enable Zoom / Pan" enableZoom={true}/>
<VisSankey label="Enable Zoom / Pan" :enableZoom="true" />
<VisSankey label="Enable Zoom / Pan" enableZoom={true}/>
const sankey = new Sankey<SankeyNode, SankeyLink>({
label: "Enable Zoom / Pan",
enableZoom: true
})
Labels
The following customization options are available for Node labels:
Label Background
For a chart with many nodes, it might be useful to add a background by setting the labelBackground property to true:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisSankey labelBackground={true}/>
<vis-sankey [labelBackground]="true"></vis-sankey>
<VisSankey labelBackground={true}/>
<VisSankey :labelBackground="true" />
<VisSankey labelBackground={true}/>
const sankey = new Sankey<SankeyNode, SankeyLink>({ labelBackground: true })
Label Fitting
By default, node labels that exceed the width constraint will be trimmed to exclude the middle. For the following properties, the default configuration for Sankey looks like:
{
labelFit: FitMode.Trim,
labelMaxWidth: 70,
labelTrimMode: TrimMode.Middle,
labelExpandTrimmedOnHover: true,
}
For overflowing labels, the default configuration renders as:
FitMode.Wrap
You can disable trimming by setting labelFit to FitMode.Wrap or 'wrap', which forces line breaking:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
import { VisSingleContainer, VisSankey } from '@unovis/react'
function Component(props) {
const data: SankeyData = props.data
const label = (d: SankeyNode) => `Long node name : ${d.id}`
return (
<VisSingleContainer data={data}>
<VisSankey
label={label}
labelFit="wrap"
labelMaxWidth={80}
labelForceWordBreak={false}
/>
</VisSingleContainer>
)
}
@Component({
templateUrl: 'template.html'
})
export class Component {
@Input data: SankeyData;
label = (d: SankeyNode) => `Long node name : ${d.id}`
}
<vis-single-container [data]="data">
<vis-sankey
[label]="label"
labelFit="wrap"
[labelMaxWidth]="80"
[labelForceWordBreak]="false"
></vis-sankey>
</vis-single-container>
<script lang='ts'>
import { VisSingleContainer, VisSankey } from '@unovis/svelte'
export let data: SankeyData
const label = (d: SankeyNode) => `Long node name : ${d.id}`
</script>
<VisSingleContainer {data}>
<VisSankey
{label}
labelFit="wrap"
labelMaxWidth={80}
labelForceWordBreak={false}
/>
</VisSingleContainer>
<script setup lang="ts">
import { VisSingleContainer, VisSankey } from '@unovis/vue'
const props = defineProps<{ data: SankeyData }>()
const label = (d: SankeyNode) => `Long node name : ${d.id}`
</script>
<template>
<VisSingleContainer :data="data">
<VisSankey
:label="label"
labelFit="wrap"
:labelMaxWidth="80"
:labelForceWordBreak="false"
/>
</VisSingleContainer>
</template>
import { VisSingleContainer, VisSankey } from '@unovis/solid'
function Component(props) {
const data: SankeyData = () => props.data
const label = (d: SankeyNode) => `Long node name : ${d.id}`
return (
<VisSingleContainer data={data()}>
<VisSankey
label={label}
labelFit="wrap"
labelMaxWidth={80}
labelForceWordBreak={false}
/>
</VisSingleContainer>
)
}
import { SingleContainer, Sankey } from '@unovis/ts'
import { data, SankeyNode, SankeyLink } from './data'
const container = new SingleContainer<SankeyNode, SankeyLink>(node, {
component: new Sankey<SankeyNode, SankeyLink>({
label: (d: SankeyNode) => `Long node name : ${d.id}`,
labelFit: "wrap",
labelMaxWidth: 80,
labelForceWordBreak: false
})
}, data)
When labelFit is set to FitMode.Wrap, you can change which characters to denote a new line
with the labelTextSeparator property.
(default: [' ', '-']).
FitMode.Trim
You can the labelTrimMode property to change which portion of the labels you want to trim:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisSankey label={label} labelMaxWidth={80} labelTrimMode="start"/>
<vis-sankey
[label]="label"
[labelMaxWidth]="80"
labelTrimMode="start"
></vis-sankey>
<VisSankey {label} labelMaxWidth={80} labelTrimMode="start"/>
<VisSankey :label="label" :labelMaxWidth="80" labelTrimMode="start" />
<VisSankey label={label} labelMaxWidth={80} labelTrimMode="start"/>
const sankey = new Sankey<SankeyNode, SankeyLink>({
label,
labelMaxWidth: 80,
labelTrimMode: "start"
})
Label Placement
The following properties deal with node label placement:
labelPosition, which corresponds to the horizontal placement relative to the node (default:Position.Auto);labelVerticalAlign, for vertical alignment (default:VerticalAlign.Middle);labelVisibility, which accepts a custom function that when returns false, the label will be hidden altogether.
Automatic Label Sizing
Labels can optionally take the available horizontal space between nodes automatically.
- labelMaxWidthTakeAvailableSpace: enable automatic width (default:
false). - labelMaxWidthTakeAvailableSpaceTolerance: tolerance for available space calculation; by default computed from label and sub-label font sizes.
- Precedence: when provided,
labelMaxWidthalways overrides automatic sizing.