Karsa Wang 's Blog

记录一些问题,也许对其他人也有所助益


第一次听说桑基图

桑基图(Sankey Diagram)是一种用于可视化流动和比例的图表类型,常用于展示能量、物质或成本在系统中的流动。它以其宽度可变的流向箭头来突出各个流动的相对大小。

主要由节点和流来组成,流的宽度表示流量大小,流动方向通常上是从左向右。通常上,最左侧节点的流出量相加等于最右侧节点的流入量。

这是一个很常规的桑基图示例: 示例图片

我看到的需求是在react native app中实现一个非常规的桑基图,大概如下视频所示:

主要用了 shopify/react-native-skia 和 d3-sankey 来实现。跟默认的逻辑不同的有以下几点:

  1. 节点定制,这个简单;
  2. 节点分为文字节点和块节点;
  3. 节点的层级需要定义;
  4. 流在块节点上的宽度和在文字节点上的宽度不同;
  5. 流也分类,有实线的,有虚线的。

简单讲一下实现逻辑:

  1. 定义不同类型的节点(文本节点和块节点);
  2. 设置节点的层级(最左边是第0层);
  3. 自定义流的绘制,连接块节点的一端宽度和文字节点一端宽度不同;

定制流的逻辑:

  1. 遍历每个流,获取到两端节点的位置,P1, P2, 按照不同宽度w1, w2, 获取到四个点, A:(P1x,P1y+ w1/2),B:(P1x,P1y-w1/2),C:(P2x,P2y+ w2/2),D:(P2x,P2y-w2/2)。
  2. 然后用直线连接AB,CD,用贝塞尔曲线连接AC,BD,形成一个path。
  3. 涂满整个path就是实线流;
  4. 引入贝塞尔曲线计算公式,可以通过开始点、结束点、控制点、步长,计算可以分割贝塞尔曲线上的精确点,由此可以绘制虚线。