图表
SankeyChart - 桑基图
一个量在流经各个阶段时去了哪里。
用法
什么时候用它
来自@misoto22/folio/charts
import { SankeyChart } from '@misoto22/folio/charts'说明
一个量在流经各个阶段时去了哪里——用来画漏斗、预算、能耗或流量拆解。
这是这里唯一一张数据是图(graph)而不是表的图表,所以它接收的是 { nodes, links } 而不是数据行,表格视图列的也是流而不是节点。
结构
| 部件 | 说明 |
|---|---|
| 图框必填 | ChartFigure 的那个 <figure>,由 title 命名,图形装在一个 ChartContainer 里。 |
| 节点矩形必填 | 根节点自己的节点渲染器。名字在 config 里的节点,用它对应的渐变上色;不在的则退回 currentColor,所以它只是被画得素净,不会丢掉。 |
| 节点标签 | <SankeyChart.NodeLabel>,组合在 <SankeyChart.Node> 里面,而且完全要自己选择加上。不加,图上就没有任何东西有名字——这里没有图例,所以名字只存在于 tooltip 和隐藏表格里。 |
| 流带 | <SankeyChart.Link>。gradient 把源端的颜色渐变到目标端的颜色,是真正读起来像流动的那一种;solid 则彻底放弃颜色,让节点矩形去承担身份。 |
| 隐藏数据表必填 | 那张 sr-only 表格列的是连接——从哪、到哪、值多少——而不是节点,因为一张节点合计表会丢掉这张图存在的全部理由:每一条“从哪到哪”。 |
实践建议
推荐
- 把 nodes 数组当成一张地址表。一条连接的 source 和 target 是它的索引,所以在最前面插入一个节点,会不声不响地把每一条连接重新指向另一对节点——而且布局照样渲染得出来,所以这件事该由测试来盯,不是靠眼睛。
- 组合 <SankeyChart.Node>,并在它里面放一个 <SankeyChart.NodeLabel>。名字要自己选择加上,而且没有图例可退,所以一张没有标签的桑基图就是一堆匿名的灰带子。
- 让各条流守恒,否则就给差额单独一个有名字的节点。带子的宽度是屏幕上唯一的算术,而一个悄悄少掉百分之八的节点,读起来就只是一个小一点的节点。
避免
- 当那个量只沿一条路径收窄时,不要用它。那是 FunnelChart 的事;桑基图会把全部布局预算花在根本不存在的分叉上。
- 不要在同一列里放二十个节点。nodePadding 是 10px,布局把剩下的空间分掉,所以超过十来个,一个节点矩形就只有几像素高,居中在它上面的标签根本无处安放。
示例
默认
这里唯一一张数据是图而不是表的图表:它收的是节点和连边,而每条连边用在节点数组里的下标来指认它的两端。宽度就是量,而一个节点画多高,取决于流经它的量,所以数据里漏掉的一条连边,会悄悄把它本该喂养的那个节点缩小——而一条回流到它已经离开过的阶段的流,根本没有从左到右的读法。隐藏表格列的是流、而不是节点,理由相同:一张节点合计的表格,会把这张图存在所要陈述的每一组「从哪到哪」全部丢掉。NodeLabel 配 showValues 会把数字印在每个名字旁边,因为一条带子的宽度,用眼睛量起来并不比一个扇区的角度更容易。
| from | To | Value |
|---|---|---|
| Search | Signed up | 42 |
| Search | Browsed | 68 |
| Social | Browsed | 51 |
| Social | Left | 34 |
| Direct | Signed up | 27 |
| Direct | Left | 18 |
连线与标签
同一张图上的四种连边变体和两种标签位置。gradient 把源端的颜色淡入到目标端的颜色,是那个读起来像流动的选项;source 和 target 把整条带子归属给某一端,而当问题是「这是从哪来的」而不是「它后来变成了什么」时,就去拿它;solid 完全放弃颜色,让节点矩形去承载身份。标签设成 inside 时,需要一个宽到装得下它的节点,这也是为什么那个开关会把 nodeWidth 从 12 一下抬到 76——留在 12 上,标签会跑到它本该待在里面的那个形状之外。
| from | To | Value |
|---|---|---|
| Search | Signed up | 42 |
| Search | Browsed | 68 |
| Social | Browsed | 51 |
| Social | Left | 34 |
| Direct | Signed up | 27 |
| Direct | Left | 18 |
加载中
骨架,也是这一组里唯一一个无视自己数据的:isLoading 设着的时候,这张图会被换成一张固定的八节点、十一连边的图,于是在任何东西到达之前,这个形状读起来就已经是一张桑基图,而 data 属性只需要满足类型即可。节点和连边是错相脉动的、不是一起,正是这一点让一份骨架不至于读起来像一整块在眨眼;在 prefers-reduced-motion 下,它们改为停在固定的不透明度上。Node 和 Link 是根节点会读取的插槽,所以在这里组合它们不花任何代价,而这也正是图数据落下来时这张图能以本来面目回来的原因。
类型
export type SankeyLinkVariant = 'gradient' | 'solid' | 'source' | 'target'
export type SankeyLabelPosition = 'inside' | 'outside'无障碍
- title 必填。隐藏表格列的是“流”而不是节点——一张节点合计表会丢掉这张图存在的全部理由:每一条“从哪到哪”。
- 四种连接样式:gradient 读起来像流动,source 与 target 把整条带归属到某一端,solid 放弃颜色、让节点去承担身份。