A Sankey Series visualises movement or change between different items, using nodes and links.
Simple Sankey Copy Link
import {
AgChartOptions,
AgCharts,
AnimationModule,
ContextMenuModule,
CrosshairModule,
LegendModule,
ModuleRegistry,
SankeySeriesModule,
} from "ag-charts-enterprise";
ModuleRegistry.registerModules([
AnimationModule,
CrosshairModule,
LegendModule,
SankeySeriesModule,
ContextMenuModule,
]);
const options: AgChartOptions = {
title: {
text: "UK Power Generation",
},
subtitle: {
text: "2023",
},
data: [
{ from: "Wind", to: "Renewables", size: 79 },
{ from: "Nuclear", to: "Renewables", size: 38 },
{ from: "Biomass", to: "Renewables", size: 14 },
{ from: "Solar", to: "Renewables", size: 13 },
{ from: "Hydro", to: "Renewables", size: 3 },
{ from: "Natural Gas", to: "Fossil Fuels", size: 86 },
{ from: "Coal", to: "Fossil Fuels", size: 3 },
{ from: "Imports", to: "Total", size: 33 },
{ from: "Fossil Fuels", to: "Total", size: 89 },
{ from: "Renewables", to: "Total", size: 147 },
],
series: [
{
type: "sankey",
fromKey: "from",
toKey: "to",
sizeKey: "size",
sizeName: "Total (GWh)",
},
],
};
options.container = document.getElementById("myChart");
const chart = AgCharts.create(options);
To create a Sankey Series, use the sankey series type.
{
series: [
{
type: 'sankey',
fromKey: 'from',
toKey: 'to',
sizeKey: 'size',
},
],
}In this configuration:
fromKeydefines the start node of each link.toKeydefines the end node of each link.sizeKeydefines the size of each link.
Circular loops are not allowed in Sankey diagrams, and links forming a circular loop will be removed.
Node Layout Copy Link
Horizontal Alignment Copy Link
The horizontal placement of the nodes can be customised using the alignment property on node.
import {
AgCharts,
AgFlowProportionChartOptions,
AgSankeySeriesOptions,
AnimationModule,
ContextMenuModule,
CrosshairModule,
LegendModule,
ModuleRegistry,
SankeySeriesModule,
} from "ag-charts-enterprise";
ModuleRegistry.registerModules([
AnimationModule,
CrosshairModule,
LegendModule,
SankeySeriesModule,
ContextMenuModule,
]);
const options: AgFlowProportionChartOptions = {
title: {
text: "Company Revenue",
},
subtitle: {
text: "2023",
},
data: [
{ from: "Employees", to: "Sales", size: 2 },
{ from: "Contractors", to: "Sales", size: 2 },
{ from: "Sales", to: "Revenue", size: 4 },
{ from: "Licenses", to: "Revenue", size: 4 },
{ from: "Revenue", to: "Cost of Sales", size: 1 },
{ from: "Revenue", to: "Profit", size: 7 },
{ from: "Profit", to: "Other Expenses", size: 2 },
{ from: "Profit", to: "Operational Profit", size: 5 },
{ from: "Operational Profit", to: "Shareholders", size: 3 },
{ from: "Operational Profit", to: "Employee Bonuses", size: 2 },
],
series: [
{
type: "sankey",
fromKey: "from",
toKey: "to",
sizeKey: "size",
sizeName: "Total (USD millions)",
node: {
alignment: "left",
},
},
],
};
options.container = document.getElementById("myChart");
const chart = AgCharts.create(options);
function alignmentChange(event: Event) {
const value = (event.target as HTMLInputElement).value as
| "left"
| "right"
| "center"
| "justify";
(options.series![0] as AgSankeySeriesOptions).node!.alignment = value;
chart.update(options);
}
if (typeof window !== "undefined") {
// Attach external event handlers to window so they can be called from index.html
(<any>window).alignmentChange = alignmentChange;
}
{
series: [
{
type: 'sankey',
fromKey: 'from',
toKey: 'to',
sizeKey: 'size',
node: {
alignment: 'left',
},
},
],
}There are four values supported:
leftmoves nodes as far left as possible.rightmoves nodes as far right as possible.centermoves nodes as close to the centre as possible.justifymoves nodes as far left as possible, except for the last nodes, which are pushed right.
Vertical Alignment Copy Link
The vertical placement of the nodes can be customised using the verticalAlignment property on node.
import {
AgCharts,
AgFlowProportionChartOptions,
AgSankeySeriesOptions,
AnimationModule,
ContextMenuModule,
CrosshairModule,
LegendModule,
ModuleRegistry,
SankeySeriesModule,
} from "ag-charts-enterprise";
ModuleRegistry.registerModules([
AnimationModule,
CrosshairModule,
LegendModule,
SankeySeriesModule,
ContextMenuModule,
]);
const options: AgFlowProportionChartOptions = {
title: {
text: "Company Revenue",
},
subtitle: {
text: "2023",
},
data: [
{ from: "Employees", to: "Sales", size: 2 },
{ from: "Contractors", to: "Sales", size: 2 },
{ from: "Sales", to: "Revenue", size: 4 },
{ from: "Licenses", to: "Revenue", size: 4 },
{ from: "Revenue", to: "Cost of Sales", size: 1 },
{ from: "Revenue", to: "Profit", size: 7 },
{ from: "Profit", to: "Other Expenses", size: 2 },
{ from: "Profit", to: "Operational Profit", size: 5 },
{ from: "Operational Profit", to: "Shareholders", size: 3 },
{ from: "Operational Profit", to: "Employee Bonuses", size: 2 },
],
series: [
{
type: "sankey",
fromKey: "from",
toKey: "to",
sizeKey: "size",
sizeName: "Total (USD millions)",
node: {
verticalAlignment: "center",
},
},
],
};
options.container = document.getElementById("myChart");
const chart = AgCharts.create(options);
function verticalAlignChange(event: Event) {
const verticalAlignment = (event.target as HTMLInputElement).value as
| "top"
| "bottom"
| "center";
(options.series![0] as AgSankeySeriesOptions).node!.verticalAlignment =
verticalAlignment;
chart.update(options);
}
if (typeof window !== "undefined") {
// Attach external event handlers to window so they can be called from index.html
(<any>window).verticalAlignChange = verticalAlignChange;
}
{
series: [
{
type: 'sankey',
fromKey: 'from',
toKey: 'to',
sizeKey: 'size',
node: {
verticalAlignment: 'top',
},
},
],
}There are three values supported:
topmoves nodes as far up as possible.bottommoves nodes as far down as possible.centerplaces the nodes in the middle and distributes evenly in each direction.
Sorting Copy Link
The order of the nodes can be customised using the sort property on node.
import {
AgCharts,
AgFlowProportionChartOptions,
AgSankeySeriesOptions,
AnimationModule,
ContextMenuModule,
CrosshairModule,
LegendModule,
ModuleRegistry,
SankeySeriesModule,
} from "ag-charts-enterprise";
ModuleRegistry.registerModules([
AnimationModule,
CrosshairModule,
LegendModule,
SankeySeriesModule,
ContextMenuModule,
]);
const options: AgFlowProportionChartOptions = {
title: {
text: "Company Revenue",
},
subtitle: {
text: "2023",
},
data: [
{ from: "Footwear", to: "North America", size: 2245 },
{ from: "Footwear", to: "Europe, Middle East & Africa", size: 1419 },
{ from: "Footwear", to: "Asia Pacific & Latin America", size: 879 },
{ from: "Footwear", to: "Greater China", size: 1022 },
{ from: "Apparel", to: "North America", size: 1405 },
{ from: "Apparel", to: "Asia Pacific & Latin America", size: 360 },
{ from: "Apparel", to: "Europe, Middle East & Africa", size: 794 },
{ from: "Apparel", to: "Greater China", size: 490 },
{ from: "Equipment", to: "North America", size: 132 },
{ from: "Equipment", to: "Europe, Middle East & Africa", size: 100 },
{ from: "Equipment", to: "Asia Pacific & Latin America", size: 59 },
{ from: "Equipment", to: "Greater China", size: 32 },
{ from: "North America", to: "NIKE Brand", size: 3782 },
{ from: "Europe, Middle East & Africa", to: "NIKE Brand", size: 2313 },
{ from: "Greater China", to: "NIKE Brand", size: 1544 },
{ from: "Asia Pacific & Latin America", to: "NIKE Brand", size: 1298 },
{ from: "Global Brand Divisions", to: "NIKE Brand", size: 9 },
{ from: "NIKE Brand", to: "Revenues", size: 8946 },
{ from: "Converse", to: "Revenues", size: 425 },
{ from: "Corporate", to: "Revenues", size: 3 },
{ from: "Revenues", to: "Cost of sales", size: 5269 },
{ from: "Revenues", to: "Gross profit", size: 4105 },
{
from: "Gross profit",
to: "Selling and administrative expense",
size: 3142,
},
{ from: "Gross profit", to: "Interest expense", size: 14 },
{ from: "Gross profit", to: "Income before taxes", size: 949 },
{ from: "Other income", to: "Income before taxes", size: 48 },
{
from: "Selling and administrative expense",
to: "Demand creation expense",
size: 910,
},
{
from: "Selling and administrative expense",
to: "Operating overhead expense",
size: 2232,
},
{ from: "Income before taxes", to: "Tax expense", size: 150 },
{ from: "Income before taxes", to: "Net income", size: 847 },
],
series: [
{
type: "sankey",
fromKey: "from",
toKey: "to",
sizeKey: "size",
sizeName: "Total (USD millions)",
node: {
alignment: "center",
sort: "auto",
},
},
],
};
options.container = document.getElementById("myChart");
const chart = AgCharts.create(options);
function sortChange(event: Event) {
const sort = (event.target as HTMLInputElement).value as
| "data"
| "ascending"
| "descending"
| "auto";
(options.series![0] as AgSankeySeriesOptions).node!.sort = sort;
chart.update(options);
}
if (typeof window !== "undefined") {
// Attach external event handlers to window so they can be called from index.html
(<any>window).sortChange = sortChange;
}
There are three values supported:
datasorts nodes in the same order as they first appear in thedataarray.ascendinganddescendingsort nodes alphanumerically by their displayed labels.autosorts nodes to reduce overlapping links and produce a cleaner layout.
Label Placement Copy Link
Labels can be placed to the left, right or centred over nodes using the placement property.
import {
AgCharts,
AgFlowProportionChartOptions,
AgSankeySeriesOptions,
AnimationModule,
ContextMenuModule,
CrosshairModule,
LegendModule,
ModuleRegistry,
SankeySeriesModule,
} from "ag-charts-enterprise";
ModuleRegistry.registerModules([
AnimationModule,
CrosshairModule,
LegendModule,
SankeySeriesModule,
ContextMenuModule,
]);
const options: AgFlowProportionChartOptions = {
title: {
text: "Company Revenue",
},
subtitle: {
text: "2023",
},
data: [
{ from: "Employees", to: "Sales", size: 2 },
{ from: "Contractors", to: "Sales", size: 2 },
{ from: "Sales", to: "Revenue", size: 4 },
{ from: "Licenses", to: "Revenue", size: 4 },
{ from: "Revenue", to: "Cost of Sales", size: 1 },
{ from: "Revenue", to: "Profit", size: 7 },
{ from: "Profit", to: "Other Expenses", size: 2 },
{ from: "Profit", to: "Operational Profit", size: 5 },
{ from: "Operational Profit", to: "Shareholders", size: 3 },
{ from: "Operational Profit", to: "Employee Bonuses", size: 2 },
],
series: [
{
type: "sankey",
fromKey: "from",
toKey: "to",
sizeKey: "size",
sizeName: "Total (USD millions)",
label: {
placement: "right",
edgePlacement: "outside",
},
},
],
};
options.container = document.getElementById("myChart");
const chart = AgCharts.create(options);
function placementChange(event: Event) {
const value = (event.target as HTMLInputElement).value as
| "left"
| "right"
| "center";
(options.series![0] as AgSankeySeriesOptions).label!.placement = value;
chart.update(options);
}
function edgePlacementChange(event: Event) {
const value = (event.target as HTMLInputElement).value;
(options.series![0] as AgSankeySeriesOptions).label!.edgePlacement =
value === "default" ? undefined : (value as "inside" | "outside");
chart.update(options);
}
if (typeof window !== "undefined") {
// Attach external event handlers to window so they can be called from index.html
(<any>window).placementChange = placementChange;
(<any>window).edgePlacementChange = edgePlacementChange;
}
The optional edgePlacement property sets the first and last node labels to 'inside' or 'outside', defaulting to the placement value if unspecified.
Customisation Copy Link
Node Style Copy Link
import {
AgChartOptions,
AgCharts,
AnimationModule,
ContextMenuModule,
CrosshairModule,
LegendModule,
ModuleRegistry,
SankeySeriesModule,
} from "ag-charts-enterprise";
ModuleRegistry.registerModules([
AnimationModule,
CrosshairModule,
LegendModule,
SankeySeriesModule,
ContextMenuModule,
]);
const options: AgChartOptions = {
title: {
text: "UK Power Generation",
},
subtitle: {
text: "2023",
},
data: [
{ from: "Wind", to: "Renewables", size: 79 },
{ from: "Nuclear", to: "Renewables", size: 38 },
{ from: "Biomass", to: "Renewables", size: 14 },
{ from: "Solar", to: "Renewables", size: 13 },
{ from: "Hydro", to: "Renewables", size: 3 },
{ from: "Natural Gas", to: "Fossil Fuels", size: 86 },
{ from: "Coal", to: "Fossil Fuels", size: 3 },
{ from: "Imports", to: "Total", size: 33 },
{ from: "Fossil Fuels", to: "Total", size: 89 },
{ from: "Renewables", to: "Total", size: 147 },
],
series: [
{
type: "sankey",
fromKey: "from",
toKey: "to",
sizeKey: "size",
sizeName: "Total (GWh)",
node: {
fill: "#34495e",
stroke: "#2c3e50",
strokeWidth: 2,
},
},
],
};
options.container = document.getElementById("myChart");
const chart = AgCharts.create(options);
The styling of all nodes can be customised using the node property.
{
series: [
{
type: 'sankey',
fromKey: 'from',
toKey: 'to',
sizeKey: 'size',
node: {
fill: '#34495e',
stroke: '#2c3e50',
strokeWidth: 2,
},
},
],
} Link Style Copy Link
import {
AgChartOptions,
AgCharts,
AnimationModule,
ContextMenuModule,
CrosshairModule,
LegendModule,
ModuleRegistry,
SankeySeriesModule,
} from "ag-charts-enterprise";
ModuleRegistry.registerModules([
AnimationModule,
CrosshairModule,
LegendModule,
SankeySeriesModule,
ContextMenuModule,
]);
const options: AgChartOptions = {
title: {
text: "UK Power Generation",
},
subtitle: {
text: "2023",
},
data: [
{ from: "Wind", to: "Renewables", size: 79 },
{ from: "Nuclear", to: "Renewables", size: 38 },
{ from: "Biomass", to: "Renewables", size: 14 },
{ from: "Solar", to: "Renewables", size: 13 },
{ from: "Hydro", to: "Renewables", size: 3 },
{ from: "Natural Gas", to: "Fossil Fuels", size: 86 },
{ from: "Coal", to: "Fossil Fuels", size: 3 },
{ from: "Imports", to: "Total", size: 33 },
{ from: "Fossil Fuels", to: "Total", size: 89 },
{ from: "Renewables", to: "Total", size: 147 },
],
series: [
{
type: "sankey",
fromKey: "from",
toKey: "to",
sizeKey: "size",
sizeName: "Total (GWh)",
link: {
fill: "#34495e",
fillOpacity: 0.25,
stroke: "#2c3e50",
strokeWidth: 1,
strokeOpacity: 0.25,
},
},
],
};
options.container = document.getElementById("myChart");
const chart = AgCharts.create(options);
The styling of all links can be customised using the link property.
{
series: [
{
type: 'sankey',
fromKey: 'from',
toKey: 'to',
sizeKey: 'size',
link: {
fill: '#34495e',
fillOpacity: 0.25,
stroke: '#2c3e50',
strokeWidth: 1,
strokeOpacity: 0.25,
},
},
],
} Sankey Chart Examples Copy Link
See more Sankey Chart examples in the AG Charts Gallery.
API Reference Copy Link
Properties available on the AgSankeySeriesOptions interface.
- type required
'sankey' - Configuration for the Sankey Series.
- getItemId
Function - A callback to provide a stable identifier for each node, exposed as `itemId` in events and active state. The returned identifier must be unique across nodes and links, which share one `itemId` namespace (links default to `link-<index>`). If not supplied, the node name is used as its identifier.
- id
stringdefault: auto-generated value - Primary identifier for the series. This is provided as `seriesId` in user callbacks to differentiate multiple series. Auto-generated ids are subject to future change without warning, if your callbacks need to vary behaviour by series please supply your own unique `id` value.
- context
ContextDefault - Context object to use in callbacks.
- data
DatumDefault[] - The data to use when rendering the series. If this is not supplied, data must be set on the chart instead.
- visible
boolean - Whether to display the series.
- cursor
string - The cursor to use for hovered markers. This config is identical to the CSS `cursor` property.
- highlight
AgHighlightOptions - Configuration for highlighting when a series or legend item is hovered over.
- nodeClickRange
InteractionRange - Range from a node that a click triggers the listener.
- showInLegend
boolean - Whether to include the series in the legend.
- listeners
AgSeriesListeners - A map of event names to event listeners.
- fromKey
string - The key containing the start node of each link.
- toKey
string - The key containing the end node of each link.
- sizeKey
string - The key containing the size of each link.
- sizeName
string - A human-readable description of the size values. If supplied, this will be shown in the default tooltip and passed to the tooltip renderer as one of the parameters.
- label
AgSankeySeriesLabelOptions - Options for the label for each node.
- fills
AgColorType[] - The colours to cycle through for the fills of the nodes and links. An array of colour strings, or fill objects for gradients, patterns, or images.
- strokes
CssColor[] - The colours to cycle through for the strokes of the nodes and links.
- link
AgSankeySeriesLinkOptions - Options for the links.
- node
AgSankeySeriesNodeOptions - Options for the nodes.
- tooltip
AgSeriesTooltip - Series-specific tooltip configuration.
Properties available on the AgSankeySeriesOptions interface.
- type required
'sankey' - Configuration for the Sankey Series.
- getItemId
Function - A callback to provide a stable identifier for each node, exposed as `itemId` in events and active state. The returned identifier must be unique across nodes and links, which share one `itemId` namespace (links default to `link-<index>`). If not supplied, the node name is used as its identifier.
- id
stringdefault: auto-generated value - Primary identifier for the series. This is provided as `seriesId` in user callbacks to differentiate multiple series. Auto-generated ids are subject to future change without warning, if your callbacks need to vary behaviour by series please supply your own unique `id` value.
- context
ContextDefault - Context object to use in callbacks.
- data
DatumDefault[] - The data to use when rendering the series. If this is not supplied, data must be set on the chart instead.
- visible
boolean - Whether to display the series.
- cursor
string - The cursor to use for hovered markers. This config is identical to the CSS `cursor` property.
- highlight
AgHighlightOptions - Configuration for highlighting when a series or legend item is hovered over.
- nodeClickRange
InteractionRange - Range from a node that a click triggers the listener.
- showInLegend
boolean - Whether to include the series in the legend.
- listeners
AgSeriesListeners - A map of event names to event listeners.
- fromKey
string - The key containing the start node of each link.
- toKey
string - The key containing the end node of each link.
- sizeKey
string - The key containing the size of each link.
- sizeName
string - A human-readable description of the size values. If supplied, this will be shown in the default tooltip and passed to the tooltip renderer as one of the parameters.
- label
AgSankeySeriesLabelOptions - Options for the label for each node.
- fills
AgColorType[] - The colours to cycle through for the fills of the nodes and links. An array of colour strings, or fill objects for gradients, patterns, or images.
- strokes
CssColor[] - The colours to cycle through for the strokes of the nodes and links.
- link
AgSankeySeriesLinkOptions - Options for the links.
- node
AgSankeySeriesNodeOptions - Options for the nodes.
- tooltip
AgSeriesTooltip - Series-specific tooltip configuration.