You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

D3 Sankey图表自定义:如何调整节点高度并实现节点垂直居中

D3 Sankey 图表自定义节点高度+垂直居中实现方案

实现逻辑

D3 的 sankey 布局默认会根据节点流量权重自动计算节点高度,要实现需求可以按以下步骤操作:

  • 覆盖节点高度默认计算逻辑,自定义节点高度规则(固定高度或自定义权重计算均可)
  • 将同列节点分组,基于画布可用高度计算顶部偏移量,实现整列节点垂直居中
  • 同步更新链路坐标,保证链路和节点正确衔接

核心代码示例

// 依赖版本建议d3-sankey v7+
import { sankey, sankeyLinkHorizontal } from 'd3-sankey';

// 基础配置可按需调整
const width = 800;
const height = 500;
const CUSTOM_NODE_HEIGHT = 30; // 自定义节点固定高度
const NODE_PADDING = 15; // 节点垂直间距

// 初始化sankey布局实例
const sankeyInstance = sankey()
  .nodeWidth(20)
  .nodePadding(NODE_PADDING)
  .extent([[20, 20], [width - 20, height - 20]]);

// 传入原始节点、链路数据生成初始布局
const layoutData = sankeyInstance({
  nodes: yourNodeData,
  links: yourLinkData
});

// 按x坐标把节点分到对应列
const columnGroups = {};
layoutData.nodes.forEach(node => {
  const columnKey = node.x0;
  if (!columnGroups[columnKey]) columnGroups[columnKey] = [];
  columnGroups[columnKey].push(node);
});

// 逐列调整节点位置
Object.values(columnGroups).forEach(columnNodes => {
  // 计算当前列所有节点+间距的总高度
  const totalColumnContentHeight = columnNodes.length * CUSTOM_NODE_HEIGHT + NODE_PADDING * (columnNodes.length - 1);
  // 计算垂直居中需要的顶部偏移
  const availableHeight = sankeyInstance.extent()[1][1] - sankeyInstance.extent()[0][1];
  const topOffset = (availableHeight - totalColumnContentHeight) / 2;

  // 重写每个节点的y坐标和高度
  columnNodes.forEach((node, index) => {
    node.y0 = topOffset + index * (CUSTOM_NODE_HEIGHT + NODE_PADDING);
    node.y1 = node.y0 + CUSTOM_NODE_HEIGHT;
  });
});

// 更新链路布局适配新节点位置
sankeyInstance.update(layoutData);

// 后续渲染节点示例
svg.selectAll('.sankey-node')
  .data(layoutData.nodes)
  .join('rect')
  .attr('class', 'sankey-node')
  .attr('x', d => d.x0)
  .attr('y', d => d.y0)
  .attr('width', d => d.x1 - d.x0)
  .attr('height', d => d.y1 - d.y0)
  .attr('fill', '#2196F3');

// 后续渲染链路示例
svg.selectAll('.sankey-link')
  .data(layoutData.links)
  .join('path')
  .attr('class', 'sankey-link')
  .attr('d', sankeyLinkHorizontal())
  .attr('fill', 'none')
  .attr('stroke', '#90CAF9')
  .attr('stroke-opacity', 0.5)
  .attr('stroke-width', d => Math.max(1, d.width));

效果对比

默认D3 Sankey图表效果:
默认D3 Sankey图表效果
调整后目标效果:
目标Sankey图表效果

注意事项

  • 如果需要非固定的自定义节点高度,只需要修改CUSTOM_NODE_HEIGHT的计算逻辑,按规则给每个节点设置不同的y1 - y0差值即可。
  • 如果你使用的是v4/v5版本的旧版d3-sankey,没有内置的update方法,可以手动遍历链路调整坐标:每个链路的y0设置为源节点的垂直中间位置加上对应流量的偏移,y1设置为目标节点的垂直中间位置加上对应流量的偏移即可。

内容的提问来源于stack exchange,提问作者Руслан Більмаковський

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 20:36:03