图表
ComposedChart - 组合图
同一根轴上的柱与线——体量,以及它变化的速度。
用法
什么时候用它
来自@misoto22/folio/charts
import { ComposedChart } from '@misoto22/folio/charts'说明
同一根轴上的柱与线——用来回答“体量,以及它变化的速度”。
永远只有一根轴。刻度不同的两个度量应该拆成两张图,或者统一到同一基准;第二根 Y 轴让作者自己决定两条线在哪里相交,这是一张图能做的最具误导性的事。
结构
| 部件 | 说明 |
|---|---|
| 图框必填 | ChartFigure 的那个 <figure>,由 title 命名,组合起来的各种标记都装在同一个测过尺寸的 ChartContainer 里。 |
| 唯一那根值轴必填 | <ComposedChart.YAxis>。只有一根,这就是整个设计:这里没有双轴的入口,也没有第二把刻度可配,所以两个度量是对着同一组数字读的。 |
| 柱子 | <ComposedChart.Bar>,体量。和 BarChart 一样走自定义 shape,一样带透明的命中矩形,生长动画一样锚定在图表自身的起始时刻、而不是每根柱子的挂载时刻,所以悬停不会让它重播。 |
| 线 | <ComposedChart.Line>,变化的速度。它继承图表的 curveType 和揭示动画,所以柱和线是作为一张图一起到达的,不是两个各走各表的动画。 |
| 列高亮 | enableHoverHighlight 会把悬停列之外的每个标记调暗,驱动它的是图表自己的 onMouseMove 索引、而不是各个标记自身的悬停——同一列里的柱和线能一起亮起来,靠的就是这一点。 |
| 刷选条与工具栏 | 容器页脚里的 <ComposedChart.Brush> 和绘图区上方的 <ComposedChart.Toolbar>。它们驱动的是同一个窗口,所以刷选出来的范围和缩放出来的范围,不会对“屏幕上到底是什么”各执一词。 |
| 隐藏数据表 | 完整数据的那张 sr-only 表格,取的不是刷选出来的窗口,所以读表格的人拿到的绝不会比 CSV 导出里的少。hideDataTable 会把它去掉,零行则什么都不渲染。 |
实践建议
推荐
- 两个度量不共享刻度时,把它们统一到同一个基准上——比如都换算成一月份的百分比。这就是这个组件刻意不提供的第二根轴的替代品。
- 超过两个标记时,组合一个 <ComposedChart.Legend>。取 --series-1 和 --series-2 的一根柱和一条线,差别只是一级灰阶和一个形状,而其中只有形状是能自我说明的。
- enableHoverHighlight 要么每个标记都设,要么一个都不设。只设在其中一个上,悬停的那一列会把自己暗掉一半,读起来像是渲染出了问题,而不是强调。
避免
- 不要借 chartProps、或者给 <ComposedChart.YAxis> 加 yAxisId,把第二根 Y 轴偷渡进来。Recharts 允许这么做;这个组件的主张是它不允许。两把独立选定的刻度,等于让作者自己决定两条线在哪里相交,这是一张图能做的最具误导性的事——而且它对任意两条序列都奏效,屡试不爽。
- 不要以为声音读法在这里也有。AreaChart、BarChart 和 LineChart 各自带着一个 Sonify 插槽,这个没有,所以在一整块仪表板上一路听过来的读者,到这里只能退回那张 sr-only 表格——这也正是 hideDataTable 在这张图上绝对不该设的原因。
示例
默认
柱子和一条线共用一根坐标轴——这是「这个体量,以及它变动的速率」的那个形状。永远只有一根数值轴:两个尺度不同的度量该分成两张图,或者一起换算到一个共同的基准上,因为第二根 y 轴让作者可以选择那些线在哪里交叉,而那是一张图表能做的最误导人的一件事。它暴露出来的这根轴就是唯一的一根,这是设计使然。
| month | Revenue | Profit |
|---|---|---|
| Jan | 4,200 | 1,800 |
| Feb | 5,800 | 2,400 |
| Mar | 4,100 | 1,600 |
| Apr | 6,200 | 2,800 |
| May | 5,400 | 2,200 |
| Jun | 7,800 | 3,400 |
样式
柱子那一半带着和普通 BarChart 一样的六种填充,线那一半带着一样的三种描边,所以组合图不是要你去学的第三套词汇——dot 插槽在线里面组合的方式,和在 LineChart 里一模一样。这也正是该拿它、而不是把两张图叠在一起的理由:一份 config、一根轴、一套 variant,以及一个会为同一行同时报出柱子和线的 tooltip。
| Revenue | Profit |
|---|---|
| 4,200 | 1,800 |
| 5,800 | 2,400 |
| 4,100 | 1,600 |
| 6,200 | 2,800 |
| 5,400 | 2,200 |
| 7,800 | 3,400 |
悬停高亮
hover 某一列时,会把它以外的每一根柱子调暗。这个高亮读的是图表自己的 tooltip 索引,而那正是它出处那边缺掉的一半:状态是有的、离开时也会被清掉,但从来没有任何东西去设过它,于是这个高亮从来没有触发过。它由指针驱动,所以它永远不能是唯一承载某个结论的东西——可点击的图例、tooltip,以及这个图形隐藏的数据表,才是键盘够得到的那些。
| Revenue | Profit |
|---|---|
| 4,200 | 1,800 |
| 5,800 | 2,400 |
| 4,100 | 1,600 |
| 6,200 | 2,800 |
| 5,400 | 2,200 |
| 7,800 | 3,400 |
区间选择条与加载中
一张仪表盘图表大半时间都待着的两种状态,并排放着。左边是三十天之上的一个 brush:作为子元素组合进来,上面那张图随后只渲染它选中的那个窗口。右边是同一张图在加载——而即便你在那儿组合了一个 brush,它也不会出现,因为 isLoading 开着时 brush 会被抑制:此刻还没有东西可供你从中挑一个窗口。
| day | Revenue | Profit |
|---|---|---|
| D1 | 3,200 | 2,700 |
| D2 | 4,378 | 2,644 |
| D3 | 5,426 | 2,480 |
| D4 | 6,229 | 2,217 |
| D5 | 6,699 | 1,873 |
| D6 | 6,783 | 1,468 |
| D7 | 6,473 | 1,027 |
| D8 | 5,803 | 1,221 |
| D9 | 4,846 | 1,649 |
| D10 | 3,708 | 2,031 |
| D11 | 3,886 | 2,342 |
| D12 | 5,005 | 2,564 |
| D13 | 5,924 | 2,682 |
| D14 | 6,544 | 2,689 |
| D15 | 6,796 | 2,586 |
| D16 | 6,652 | 2,377 |
| D17 | 6,128 | 2,077 |
| D18 | 5,282 | 1,703 |
| D19 | 4,206 | 1,279 |
| D20 | 3,380 | 968 |
| D21 | 4,547 | 1,411 |
| D22 | 5,565 | 1,822 |
| D23 | 6,323 | 2,176 |
| D24 | 6,737 | 2,450 |
| D25 | 6,762 | 2,628 |
| D26 | 6,394 | 2,699 |
| D27 | 5,675 | 2,658 |
| D28 | 4,684 | 2,507 |
| D29 | 3,529 | 2,257 |
| D30 | 4,062 | 1,922 |
无障碍
- title 必填;数据行同样会渲染成一份视觉隐藏的表格。
- 只有一根值轴。双轴图让作者自己决定两条线在哪里相交,这是一张图能做的最具误导性的事。
- enableHoverHighlight 会把悬停列之外的柱子调暗,驱动它的是图表自己的 tooltip 索引。