跳到正文
册页

数据

Sparkline - 迷你折线

一个词那么大的一串数字。

用法

什么时候用它

表格单元格里、数字旁边、一行的末尾。要精确读趋势时,它需要的是 LineChart 和属于自己的空间。

来自@misoto22/folio/charts

TSX
import { Sparkline } from '@misoto22/folio/charts'

说明

一个词那么大的一串数字——在表格单元格里、在数字旁边、在一行的末尾。

刻意不画坐标轴、不画网格、不带标签:迷你折线回答的是“这一路是什么形状”,而任何能让它回答“到底是多少”的装饰,同时也会让它大到没法内嵌——而内嵌正是选它的唯一理由。确切的值重要时,把数字印在它旁边(value 就是干这个的);需要精确读趋势时,它要的是 <LineChart> 和属于自己的空间。

不需要渲染引擎:它就是一条画在归一化 viewBox 上的 <path>,所以在表格里放一百个也不花什么代价。

结构

Sparkline anatomy
部件说明
内嵌的一行必填一个 inline-flex 的 span,占满宽度、8px 间隙,所以这串数字能待在表格单元格里或者一个数字旁边,而不把所在的那一行撑断。
图形必填一个 svg role="img",viewBox 是 0–100 乘 0–100,preserveAspectRatio="none",所以容器给多宽它就拉多宽。height 默认 28px,是唯一固定的尺寸。
线形必填那条 path、它的面积填充,或者那些柱子——由 variant 三选一。描边用的是 non-scaling-stroke,正是这一点让盒子被拉伸之后,窄单元格和宽单元格里的线一样粗。
最后一个点showLast 在最后一个读数上画的一个 2px 的点,只在 line 和 area 两个变体上。bars 变体本来就用最后一根柱子交代了这串数字的末尾,不再画点。
印出来的数值value,跟在图形后面,等宽的表格数字。它也是可访问名称里接在 label 之后的那部分,而且是这个组件唯一会印出来的数字。
数据不够的状态当活下来的有限数字不足两个时,顶替整张图形的东西:label 加上「not enough data」,排成一行等宽的元信息文字。

实践建议

推荐

  • 只要一个具体数字要紧,就要传 value。图形没有坐标轴也没有刻度,它承载的只有形状;而 value 既是唯一印出来的数字,也是追加到可访问名称后面的那个读数。不传,那个名称就退回到用 toLocaleString 处理最后一个点——一个原始数字,没有单位、没有货币,也没有旁边那一行在用的舍入方式。
  • 任何两条会被拿来互相对照的,都要固定 domain。每一串都是按自己的最小值和最大值归一化进同一个固定的盒子,所以最高点永远贴着顶边、最低点永远贴着底:一条在 4 和 6 之间走的序列,和一条在 400 到 900 之间走的序列,画出来是同一个轮廓,而它们之间的差别哪儿都没画。
  • 很长的一串要先降采样再交过来。x 方向的步长是 100 除以点数减一,再摊到单元格给的那点宽度上,所以四百个读数放进一个 200px 的单元格,彼此只隔半个像素,那条 path 会糊成一条带子。
  • 一条穿过中间的平线要读作“没有变化”,不是“压在自己的底线上”。最小值等于最大值的序列,刻度是没有宽度的,所以上面没有哪个位置比别的位置更真,每个点都落在正中——这和 Heatmap、BulletChart 对一个零跨度给出的答案是同一个,也正是这个答案,让一列迷你折线里的“没有变化”和“钉死在最差处”分得开。

避免

  • 不要以为总会渲染出一个图形状的东西。非有限的数值先被过滤掉,剩下不足两个点就返回一行文字而不是 SVG,所以新账号那一行会是一句话,而这一列里其他每一行都是图。

示例

样式

同一条走势可以被画成的三种标记:line 读的是趋势,area 把这个趋势往体量上压,而 bars 把各个读数分开,那是一个离散计数想要的。三种按设计都没有坐标轴、没有网格、没有标签——任何一件能让它回答「到底是多少」的外围装置,同时也会让它大到没法待在行内,而那本来是去拿它的唯一理由。确切的数字改由 value 印在走势旁边,而在 line 和 area 上,最后一个点会画成一个圆点,因为通常被问的就是它。

line61
area61
bars61

放进表格

一列 sparkline,每一条都钉在同一个 domain 上。这就是全部的教训:在按行各自推导的 domain 上,每一条走势的波峰和波谷都停在同样的高度,于是一个腰斩的渠道和一个翻倍的渠道画出同一幅图——这是一张 sparkline 表格变成主动误导的唯一方式。每条走势还带着自己的 label,因为读屏软件会在四个单元格里遇到四条,而这一行里没有别的东西为它们命名。

Visitors by channel, last seven weeks
ChannelTrendThis week
Organic search71k
Paid social28k
Direct29k
Referral24k

数据不足

当没有形状可画时,一条 sparkline 会做什么。少于两个点时,它印出自己的 label,后面跟着「数据不足」,而不是画一个标记:一个读数不是趋势,而把单个值对自己做归一化,会把点放在算术碰巧落到的地方,读者会把它当成一次测量。这是一个新项目第一天所处的状态,也是一个很窄的筛选条件不断触到的状态,所以值得在它出现在表格第四十行之前,先知道它长什么样。

Kestrel
HarrierHarrier, last seven days: not enough data
MerlinMerlin, last seven days: not enough data

类型

TSX
export type SparklineVariant = 'line' | 'area' | 'bars'

无障碍

  • label 必填,而且它就是全部的可访问名称:迷你折线没有坐标轴也没有图例,再没有别的东西描述它。
  • 刻意不画坐标轴。任何能让它回答“到底是多少”的装饰,同时也会让它大到没法内嵌——而内嵌正是选它的唯一理由。
  • 一列迷你折线一定要固定 domain:各自独立取域的话,每一行的波峰波谷看起来都一模一样,表格就开始主动误导人了。
  • 一条 path,不需要渲染引擎——所以在表格里放一百个也不花什么代价。