Sankey Chart 桑基图
@lark-ui/core
<SankeyChart nodes={nodes} links={links} height={300} />

安装

SankeyChart 需要将 echarts 作为 peer dependency 安装。

npm install echarts

统一导出

import { SankeyChart } from "@lark-ui/core";

按需导出

import { SankeyChart } from "@lark-ui/core/components/chart";

用法

import { SankeyChart, ChartPalette } from "@lark-ui/core";
import * as echarts from "echarts/core";
import { SankeyChart as SankeyChartType } from "echarts/charts";
import { TooltipComponent } from "echarts/components";
import { CanvasRenderer } from "echarts/renderers";

// Register required ECharts modules
echarts.use([SankeyChartType, TooltipComponent, CanvasRenderer]);

const nodes = [
  { name: "Users", value: 103600, color: ChartPalette.categorical(0) },
  { name: "Devices", value: 50800, color: ChartPalette.categorical(1) },
  { name: "Apps", value: 122600, color: ChartPalette.categorical(2) },
  { name: "Tunnels", value: 31800, color: ChartPalette.categorical(3) },
];

const links = [
  { source: 0, target: 2, value: 80000 },
  { source: 0, target: 3, value: 23600 },
  { source: 1, target: 2, value: 42600 },
  { source: 1, target: 3, value: 8200 },
];

export default function Example() {
  return <SankeyChart echarts={echarts} nodes={nodes} links={links} height={300} />;
}

示例

基础桑基图

一个简单的桑基图,展示源节点与目标节点之间的流动。

<SankeyChart nodes={nodes} links={links} height={300} />

多级流动

桑基图可以通过中间节点展示多个层级的流动。

<SankeyChart nodes={nodes} links={links} height={350} nodeWidth={20} nodePadding={15} />

全宽布局

使用 left 和 right 控制桑基图布局在其容器中的水平内边距。将两者都设为 0 可去除默认的 5% 内边距并占满整个宽度。

<SankeyChart
  nodes={nodes}
  links={links}
  height={350}
  left={0}
  right={0}
/>

富工具提示

使用 tooltipFormatter 完全掌控工具提示内容。

import { SankeyChart, type SankeyTooltipParams } from "@lark-ui/core";

const customTooltip = (params: SankeyTooltipParams) => {
  if (params.type === "node" && params.node) {
    return "<strong>" + params.name + "</strong>";
  }
  if (params.type === "link" && params.link) {
    return params.link.source + " → " + params.link.target;
  }
  return "";
};

<SankeyChart 
  nodes={nodes} 
  links={links} 
  tooltipFormatter={customTooltip} 
/>

交互

使用 onNodeClick 和 onLinkClick 处理交互。

<SankeyChart 
  nodes={nodes} 
  links={links} 
  onNodeClick={(node) => console.log(node)}
  onLinkClick={(link) => console.log(link)}
/>

下钻筛选

点击源节点即可筛选图表,仅显示它的关联项。再次点击该节点或使用重置按钮可恢复完整视图。

点击节点进行筛选
const [selectedSource, setSelectedSource] = useState<string | null>(null);

const handleNodeClick = (node: { name: string }) => {
  if (sourceNames.includes(node.name)) {
    setSelectedSource(prev => prev === node.name ? null : node.name);
  }
};

<SankeyChart
  nodes={filteredNodes}
  links={filteredLinks}
  onNodeClick={handleNodeClick}
/>

行内标签布局

使用 nodeLabelLayout="inline" 可在单行内显示节点的数值和名称。这样可以避免在较小的节点上出现标签重叠——默认的堆叠布局会导致文字相互碰撞。

<SankeyChart
  echarts={echarts}
  nodes={nodes}
  links={links}
  height={300}
  nodeLabelLayout="inline"
/>

API 参考

属性类型默认值说明
echarts*typeof echarts-由使用方导入的 ECharts 核心实例。之所以由外部传入而不是在组件内部直接导入,是为了让使用方自行决定打包进产物的 ECharts 模块(tree-shaking)。
nodes*SankeyNodeData[]-桑基图中的节点数组
links*SankeyLinkData[]-按索引连接节点的连线数组
heightnumber-图表高度,单位为像素
showNodeValuesboolean-在标签上方显示节点数值(只要有任一节点带数值,就默认为 true)
nodeLabelLayout"stacked" | "inline"-当 `showNodeValues` 为 true 时节点标签的布局方式。 - 'stacked':数值在上、名称在下(默认) - 'inline':"value name" 排在同一行(更适合小节点)
formatValue(value: number) => string-节点数值的格式化函数(默认为 `toLocaleString`)
tooltipFormatter(params: SankeyTooltipParams) => string-自定义工具提示格式化函数。返回 HTML 字符串,或返回空字符串以隐藏工具提示。
nodeWidthnumber--
nodePaddingnumber--
showTooltipboolean--
defaultNodeColorstring--
leftnumber | string-桑基图布局在图表容器中的左侧内边距。可接受数字(px)或百分比字符串。ECharts 默认值:'5%'。
rightnumber | string-桑基图布局在图表容器中的右侧内边距。可接受数字(px)或百分比字符串。ECharts 默认值:'5%'。
linkColor"gradient" | "gray"-连线的填充样式:'gradient' 表示从源节点颜色渐变到目标节点颜色,'gray' 表示使用纯灰色
linkOpacitynumber--
classNamestring--
isDarkModeboolean--