Loading...
A Sankey diagram is a specific type of flow diagram used to describe the flow from one set of values to another. Sankey diagrams have the following characteristics:
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',padding: 10,});chart.sankey().data({type: 'fetch',value: 'https://assets.antv.antgroup.com/g2/energy.json',transform: [{type: 'custom',callback: (data) => ({ links: data }),},],}).layout({nodeAlign: 'center',nodePadding: 0.03,}).scale('color', { range: schemeTableau10 }).style('labelSpacing', 3).style('labelFontWeight', 'bold').style('nodeStrokeWidth', 1.2).style('linkFillOpacity', 0.4);chart.render();
In G2, Layout is used to specify parameters for layout methods of marks with specific layout functions, such as Sankey, WordCloud, ForceGraph, etc.
({type: 'sankey',layout: {nodeAlign: 'center',nodePadding: 0.03,},});
// APIchart.sankey().layout({ nodeAlign: 'center', nodePadding: 0.03 });
Sankey diagrams support dynamic data updates using G2's built-in API changeData():
const newData = {links: [{ source: 'A', target: 'B', value: 10 },{ source: 'A', target: 'C', value: 15 },{ source: 'B', target: 'D', value: 8 },{ source: 'C', target: 'D', value: 12 },],};chart.changeData({ type: 'inline', value: newData });
Syntactic Sugar (Recommended)
G2 also provides convenient syntactic sugar, allowing you to pass array data directly like configuring other charts:
const newData = [{ source: 'A', target: 'X', value: 10 },{ source: 'A', target: 'Y', value: 15 },{ source: 'B', target: 'X', value: 20 },{ source: 'B', target: 'Y', value: 25 },];// Pass array directlychart.changeData(newData);
When passing an empty array or not providing links, the chart will display as blank:
// Clear chart - chart will display as blankchart.changeData([]);// orchart.changeData({ links: [] });
import { Chart } from '@antv/g2';const chart = new Chart({ container: 'container' });const initialData = [{ source: 'A', target: 'X', value: 10 },{ source: 'A', target: 'Y', value: 15 },{ source: 'B', target: 'X', value: 20 },];chart.sankey().data({type: 'inline',value: initialData,});chart.render();// Click event: randomly update datachart.on('element:click', () => {const randomData = initialData.map((d) => ({...d,value: Math.random() * 30 + 5,}));// Use simplified syntax to update datachart.changeData(randomData);});
| Property | Description | Type | Default |
|---|---|---|---|
| tooltip | Configure Sankey diagram tooltip, see tooltip configuration | object | See tooltip configuration |
| layout | Configure Sankey diagram layout, see layout configuration | object | See layout configuration |
| style | Configure graphic and label styles, see style configuration | object | See style configuration |
| nodeLabels | Custom node data label configuration, see nodeLabels configuration | label[] | [] |
| linkLabels | Custom link data label configuration, see linkLabels configuration | label[] | [] |
As a composite graphic, Sankey diagrams need to distinguish between nodes and links when configuring tooltip.
Unlike single mark title configuration, Sankey diagrams need to configure nodeTitle and linkTitle separately.
({tooltip: {nodeTitle: (d) => d.key,linkTitle: (d) => 'link',},});
Unlike single mark items configuration, Sankey diagrams need to configure both nodeItems and linkItems.
Like regular items, nodeItems and linkItems also support custom configuration:
({tooltip: {nodeItems: [(d, index, data, column) => {return {color: 'red', // Specify item colorname: 'Node', // Specify item namevalue: d.key, // Use y channel valuecontent: 'Custom node property',};},],linkItems: [(d, index, data, column) => {return {color: 'red', // Specify item colorname: 'Link', // Specify item namevalue: `${d.source.key}-${d.target.key}`, // Use y channel valuecontent: 'Custom link property',};},],},});
Similar to general Mark custom tooltip interaction methods, first pass custom properties in the graphic's tooltip, then use them in interaction.
Example:
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',});const data = {nodes: [{ id: 'a', key: 'Homepage', des: 'Custom node property' },{ id: 'b', key: 'Page 1', des: 'Custom node property' },{ id: 'b_1', key: 'Page 1', des: 'Custom node property' },{ id: 'c', key: 'Page 2', des: 'Custom node property' },{ id: 'c_1', key: 'Page 2', des: 'Custom node property' },{ id: 'd', key: 'Page 3', des: 'Custom node property' },{ id: 'd_1', key: 'Page 3', des: 'Custom node property' },],links: [{ source: 'a', target: 'b', value: 100 },{ source: 'b', target: 'c', value: 80 },{ source: 'b', target: 'd', value: 20 },{ source: 'c', target: 'b_1', value: 80 },{ source: 'b_1', target: 'c_1', value: 40 },{ source: 'b_1', target: 'd_1', value: 40 },],};chart.options({type: 'sankey',width: 900,height: 600,data: {value: data,transform: [{type: 'custom',callback: (data) => ({nodes: data.nodes,links: data.links,}),},],},tooltip: {nodeItems: [(d, index, data, column) => {return {content: d.des,};},],linkItems: [(d, index, data, column) => {return {color: 'red', // Specify item colorname: 'Link', // Specify item namevalue: `${d.source.key}-${d.target.key}`, // Use y channel valuecontent: 'Custom link property',};},],},layout: {nodeId: (d) => d.id,nodeAlign: 'center',nodePadding: 0.03,iterations: 25,},style: {labelSpacing: 3,labelFontWeight: 'bold',// linkFillOpacity: 0.2,// linkFill: '#3F96FF',},interaction: {tooltip: {render: (e, { items, title }) => {return `<div>${items[0].content}</div>`;},},},});chart.render();
Sankey diagram layout configuration. Specific configuration options are as follows:
Callback format: (node: any) => string. If nodeId is not specified, defaults to (node) => node.key.
Node binding field, used as unique identifier in layout.
For nodes that appear multiple times, set an id as unique identifier and configure the nodeId callback method as (node) => node.id.
Example:
import { Chart } from '@antv/g2';const chart = new Chart({container: 'container',});const data = {nodes: [{ id: 'a', key: 'Homepage' },{ id: 'b', key: 'Page 1' },{ id: 'b_1', key: 'Page 1' },{ id: 'c', key: 'Page 2' },{ id: 'c_1', key: 'Page 2' },{ id: 'd', key: 'Page 3' },{ id: 'd_1', key: 'Page 3' },],links: [{ source: 'a', target: 'b', value: 100 },{ source: 'b', target: 'c', value: 80 },{ source: 'b', target: 'd', value: 20 },{ source: 'c', target: 'b_1', value: 80 },{ source: 'b_1', target: 'c_1', value: 40 },{ source: 'b_1', target: 'd_1', value: 40 },],};chart.options({type: 'sankey',width: 900,height: 600,data: {value: data,transform: [{type: 'custom',callback: (data) => ({nodes: data.nodes,links: data.links,}),},],},layout: {nodeId: (d) => d.id,nodeAlign: 'center',nodePadding: 0.03,iterations: 25,},style: {labelSpacing: 3,labelFontWeight: 'bold',linkFillOpacity: 0.2,linkFill: '#3F96FF',},});chart.render();
Callback format: ((a: any, b: any) => number)
Node sorting method. If nodeSort is not specified, returns the current node sorting method, defaulting to undefined, meaning the vertical order of nodes within each column will be automatically determined by the layout. If nodeSort is null, the order is fixed by input. Otherwise, the order is determined by the specified sorting function; this function is passed two nodes and must return a value less than 0 if the first node should be above the second node, greater than 0 if the second node should be above the first node, or 0 if no order is specified.
Callback format: ((a: any, b: any) => number)
Link sorting method. If linkSort is not specified, returns the current link sorting method, defaulting to undefined, meaning the vertical order of links within each node will be automatically determined by the layout. If linkSort is null, the order is fixed by input. Otherwise, the order is determined by the specified sorting function; this function is passed two links and must return a value less than 0 if the first link should be above the second link, greater than 0 if the second link should be above the first link, or 0 if no order is specified.
Built-in supported types: 'left' | 'right' | 'center' | 'justify'
Callback format: ((node: any, n: number) => number
Current node alignment method. Besides the built-in types, you can also pass the current node and the graph's total depth n (maximum node depth + 1), and must return an integer between 0 and n - 1, indicating the desired horizontal position of the node in the generated graph.
Node width. Defaults to 0.02.
Node spacing. Defaults to 0.02.
Callback format: (datum: any, maxDepth: number) => number
Node depth.
Layout calculation iteration count, defaults to 6. More iterations result in more reasonable layout.
For more layout configuration, see d3-sankey
Default style configuration:
({// labellabelText: (d) => d.key,labelSpacing: 5,labelFontSize: 10,// nodenodeStroke: '#000',// linklinkFillOpacity: 0.5,linkStroke: undefined,});
Composite graphic marks need to use different prefixes to distinguish graphic configurations.
<label>: Prefix for configuring data labels.| Property | Type | Description |
|---|---|---|
| labelText | (d: any) => string | Configure default data label value for Sankey diagram, defaults to (d) => d.key |
| labelSpacing | number | Configure data label spacing for Sankey diagram, defaults to 5 |
| labelFontSize | number | Sankey diagram data label font size |
| labelFontFamily | string | Sankey diagram data label font family |
| labelFontWeight | number | Sankey diagram data label font weight |
| labelLineHeight | number | Sankey diagram data label text line height |
| labelTextAlign | string | Set current alignment for Sankey diagram data label text content, supported values: center | end | left | right | start, defaults to start |
| labelTextBaseline | string | Set current text baseline used when drawing Sankey diagram data label text, supported values: top | middle | bottom | alphabetic | hanging. Defaults to bottom |
| labelFill | string | Sankey diagram data label text fill color |
| labelFillOpacity | number | Sankey diagram data label text fill opacity |
| labelStroke | string | Sankey diagram data label text stroke |
| labelLineWidth | number | Sankey diagram data label text stroke width |
| labelLineDash | [number,number] | Sankey diagram data label stroke dash configuration, first value is dash segment length, second value is gap distance. Setting lineDash to [0,0] results in no stroke. |
| labelStrokeOpacity | number | Sankey diagram data label stroke opacity |
| labelOpacity | number | Sankey diagram data label text overall opacity |
| labelShadowColor | string | Sankey diagram data label text shadow color |
| labelShadowBlur | number | Sankey diagram data label text shadow Gaussian blur coefficient |
| labelShadowOffsetX | number | Set horizontal distance of Sankey diagram data label shadow from text |
| labelShadowOffsetY | number | Set vertical distance of Sankey diagram data label shadow from text |
| labelCursor | string | Sankey diagram data label mouse cursor style. Same as CSS cursor style, defaults to 'default'. |
<node>: Prefix for configuring nodes.| Property | Type | Description |
|---|---|---|
| nodeFill | string | Sankey diagram node fill color |
| nodeFillOpacity | number | Sankey diagram node fill opacity |
| nodeStroke | string | Sankey diagram node stroke |
| nodeStrokeOpacity | number | Sankey diagram node stroke opacity |
| nodeLineWidth | number | Sankey diagram node stroke width |
| nodeLineDash | [number,number] | Sankey diagram node stroke dash configuration, first value is dash segment length, second value is gap distance. Setting lineDash to [0,0] results in no stroke. |
| nodeOpacity | number | Sankey diagram node overall opacity |
| nodeShadowColor | string | Sankey diagram node shadow color |
| nodeShadowBlur | number | Sankey diagram node shadow Gaussian blur coefficient |
| nodeShadowOffsetX | number | Set horizontal distance of shadow from Sankey diagram node |
| nodeShadowOffsetY | number | Set vertical distance of shadow from Sankey diagram node |
| nodeCursor | string | Sankey diagram node mouse cursor style. Same as CSS cursor style, defaults to 'default'. |
<link>: Prefix for configuring links.| Property | Type | Description |
|---|---|---|
| linkFill | string | Sankey diagram link fill color |
| linkFillOpacity | number | Sankey diagram link fill opacity |
| linkStroke | string | Sankey diagram link stroke |
| linkStrokeOpacity | number | Sankey diagram link stroke opacity |
| linkLineWidth | number | Sankey diagram link stroke width |
| linkLineDash | [number,number] | Sankey diagram link stroke dash configuration, first value is dash segment length, second value is gap distance. Setting lineDash to [0,0] results in no stroke. |
| linkOpacity | number | Sankey diagram link overall opacity |
| linkShadowColor | string | Sankey diagram link shadow color |
| linkShadowBlur | number | Sankey diagram link shadow Gaussian blur coefficient |
| linkShadowOffsetX | number | Set horizontal distance of shadow from Sankey diagram link |
| linkShadowOffsetY | number | Set vertical distance of shadow from Sankey diagram link |
| linkCursor | string | Sankey diagram link mouse cursor style. Same as CSS cursor style, defaults to 'default'. |
Built-in data label configuration is as follows.
({labels: [{text,dx: (d) => (d.x[0] < 0.5 ? spacing : -spacing),...labelStyle, // User-provided custom data label styles},...nodeLabels, // User-provided custom data labels],});
Besides the built-in node data labels, you can also customize node data label configuration.
({nodeLabels: [{text: (d) => d.key,fontSize: 10, // Note!!! Drawing properties here no longer need the label prefixfill: 'red',},],});
Links don't have built-in data labels, but you can customize link data label configuration.
({linkLabels: [{text: (d) => d.key,fontSize: 10, // Note!!! Drawing properties here no longer need the label prefixfill: 'yellow',},],});
State configuration is similar to style, using different prefixes to distinguish different graphic configurations. Configurations without prefixes will apply to both graphics.
Example:
(() => {const chart = new G2.Chart();const data = {links: [{ source: 'a', target: 'b', value: 100 },{ source: 'b', target: 'c', value: 80 },{ source: 'b', target: 'd', value: 20 },{ source: 'c', target: 'b_1', value: 80 },{ source: 'b_1', target: 'c_1', value: 40 },{ source: 'b_1', target: 'd_1', value: 40 },],};chart.options({type: 'sankey',width: 900,height: 600,data: {value: data,},style: {labelSpacing: 3,labelFontWeight: 'bold',linkFillOpacity: 0.5,nodeFillOpacity: 0.5, // Default opacity is 0.5},state: {active: {fillOpacity: 0.8, // Opacity is 0.8 on hoverlinkFill: 'red', // Links turn rednodeFill: 'blue', // Nodes turn blue},inactive: {linkFillOpacity: 0.4,nodeFillOpacity: 0.2, // Nodes are lighter than links},},interaction: {elementHighlight: true,},});chart.render();return chart.getContainer();})();