第一次听说桑基图
桑基图(Sankey Diagram)是一种用于可视化流动和比例的图表类型,常用于展示能量、物质或成本在系统中的流动。它以其宽度可变的流向箭头来突出各个流动的相对大小。
主要由节点和流来组成,流的宽度表示流量大小,流动方向通常上是从左向右。通常上,最左侧节点的流出量相加等于最右侧节点的流入量。
这是一个很常规的桑基图示例:
我看到的需求是在react native app中实现一个非常规的桑基图,大概如下视频所示:
主要用了 shopify/react-native-skia 和 d3-sankey 来实现。跟默认的逻辑不同的有以下几点:
- 节点定制,这个简单;
- 节点分为文字节点和块节点;
- 节点的层级需要定义;
- 流在块节点上的宽度和在文字节点上的宽度不同;
- 流也分类,有实线的,有虚线的。
简单讲一下实现逻辑:
- 定义不同类型的节点(文本节点和块节点);
- 设置节点的层级(最左边是第0层);
- 自定义流的绘制,连接块节点的一端宽度和文字节点一端宽度不同;
定制流的逻辑:
- 遍历每个流,获取到两端节点的位置,P1, P2, 按照不同宽度w1, w2, 获取到四个点, A:(P1x,P1y+ w1/2),B:(P1x,P1y-w1/2),C:(P2x,P2y+ w2/2),D:(P2x,P2y-w2/2)。
- 然后用直线连接AB,CD,用贝塞尔曲线连接AC,BD,形成一个path。
- 涂满整个path就是实线流;
- 引入贝塞尔曲线计算公式,可以通过开始点、结束点、控制点、步长,计算可以分割贝塞尔曲线上的精确点,由此可以绘制虚线。