D3.sankey桑葚图节点重叠问题解决

286 阅读4分钟

最近开发sankey图的时候发现一个bug,某些场景的数据会出现部分node重叠的情况,因此解决之后记录一下问题的原因和解决的办法

Sankey图是一种可视化工具,常用于展示流动系统中的能量、物质或资金的转移与分配。它通过宽度不等的箭头或线条,表现不同流动部分的相对量。流量的大小通过线条的宽度来表示,使得用户可以直观地看到各个节点之间的流动情况以及每个流量的比例。

什么是sankey图:

  • 流向表示:Sankey图中,线条代表不同的流动,箭头方向表示流动方向,线条的宽度表示流量的大小。
  • 节点之间的连接:节点表示系统中的不同元素,线条连接这些节点,用来表示流量从一个节点流向另一个节点。
  • 数据的直观性:通过线条的宽窄对比,用户可以快速理解复杂系统中的数据分布和流动。

image.png

发现问题

image.png

出现这个bug的时候可以看到当前这个节点会发生重叠,但是其他节点都是正常的,不知道为什么会出现这种情况,于是从数据入手看看重叠的数据是否错误,或者重叠的数据是否比较特殊

特殊数据

查看数据之后发现两个节点之所以会重叠,是因为节点的x轴设置错误,因为该节点没有上一个节点的连线,也就是说没有数据源,因为他就是数据源,所以sankey会把他默认放到第一层,但是由于当前场景比较特殊,各个节点的数据源是从后往前的,所以会存在某些节点没有数据源的情况,但是存在目标源

image.png

可以看出当前这可一块少了一个节点,就是因为该节点没有数据源

调整sankey渲染数据x轴

因为当前节点没有数据源,被sankey识别成第一个节点,因此数据会被放到第一层,所以需要在sankey处理完的数据中做下判断

let y = 0;
    let x = 0;
    let position = 1;
    // 在所有的计算步骤完成之后,手动调整节点位置
    console.log('sortedNodes123', sortedNodes);
    sortedNodes.forEach((node, index) => {
      if (node.position !== position) {
          y = 0;
          x = position * 400;  
          position = node.position;
      }
      node.x = x; 
      node.y = y;
      y += (node.dy + 65);
  });

以上代码可以忽略y的处理,只看x的处理

sortedNodes是sankey处理出来的node数据,拥有node.dx和node.dy,这个是node处理后的默认xy轴的位置, 可以通过node.x和node.y来给每个节点重新调整位置

这里我们根据position也就是node的层数来设置node的x轴而不是让sankey自动去生成node的x的位置,这样就能把每一层的node节点都按照position来走了

按照上面的代码,出来是sankey图会是这样的规律,第一层的node的x轴位置全是0,第二层x是00,第三层x是800,以此类推,这样就能把默认的x轴给修改掉

最终效果

image.png

可以看到节点已经不再重叠了,第四层的节点已经被补上,因为现在每个节点都是按照层数来设定的x轴

可以看到这个节点是没有上一层的数据源的,所以在默认的情况下会出现被设置到第一层的情况,那是因为桑葚图就是从数据源开始类似与树状的结构,都是从数据源开始的。

如果觉得有趣或有收获,请关注我的更新,给个喜欢和分享。您的支持是我写作的最大动力!

往期好文推荐