监控系统里最常见的需求是“把这组数据画成图”。拿到数组,选一个 ECharts 示例,替换字段,页面很快就有了颜色和动画。但图表能显示数据,不代表它传达了信息。
同一组设备指标,可以强调时间趋势、设备差异、异常位置或整体分布。目标不同,编码方式也不同。折线、位置、颜色和面积不是装饰属性,而是语言中的语法。
先写读图任务
配置图表前,我开始先写一句话:用户看完这张图,应该能回答什么问题。如果答案是“最近什么时候开始异常”,时间轴和阈值就比丰富的提示框更重要;如果答案是“哪台设备偏离整体”,排序和对比基线更重要。
这句话也能帮助删除无关信息。网格线、渐变、三维效果都可能增加视觉刺激,却降低比较精度。
例如“最近什么时候开始异常”这类任务,我不会把接口数组直接塞进 ECharts。中间会先形成一个和图表库无关的显示模型:
type MetricPoint = {
at: number;
value: number | null;
quality: "reported" | "missing" | "estimated";
};
type TrendView = {
unit: string;
normalRange: [number, number];
points: MetricPoint[];
};
function toSeries(view: TrendView) {
return view.points.map((point) => [
point.at,
point.quality === "reported" ? point.value : null,
]);
}null 是刻意的:ECharts 会留下断点,用户能看见数据缺失。如果把缺失值补成 0,图上会凭空出现一次故障;如果沿用上一个值,又会制造系统持续正常的假象。
让异常拥有上下文
只标红异常点并不够。用户还需要知道正常范围、前后变化和数据是否完整。监控图表必须诚实表达缺失值,不能用连线制造连续运行的假象。
工具的配置项很多,真正需要长期维护的是数据到视觉变量的映射。把这层映射写清楚,才能在换图表库或新增指标时保持一致。
| 信息 | 视觉编码 | 原因 |
|---|---|---|
| 时间 | 横向位置 | 最适合判断先后和持续时间 |
| 指标值 | 纵向位置 | 保留精确比较能力 |
| 正常范围 | 低对比背景带 | 提供上下文,不抢数据焦点 |
| 告警 | 形状 + 文本 | 不只依赖颜色,便于定位 |
| 缺失数据 | 折线断开 | 诚实表达未知 |
系列颜色反而排在后面,因为它只承担区分,不承担唯一语义。超过可稳定分辨的系列数量时,应该先减少同屏比较对象,而不是继续从调色板取颜色。
交互不能替代信息结构
提示框、缩放和联动可以提供细节,但用户不应该必须把鼠标移动到每个点上才能理解趋势。关键数值、单位、时间范围和异常说明应直接可见,交互只负责进一步探索。
图表还需要与表格或原始数据建立通道。视觉擅长发现模式,精确核对仍需要数值。为图表提供数据查看与导出,不是重复功能,而是让结论可以验证。尤其在监控场景里,可验证比视觉冲击更重要。
好的可视化不会要求用户欣赏图表,而是让他更快理解系统。图表越像语言,设计者越应该为歧义负责。
图:图表表达从业务问题开始,不从图表库 option 开始。
我现在使用的图表评审卡
每张图上线前都要回答:读者要做什么决定;横纵轴单位和时间范围是什么;缺失、零和估算怎样区分;颜色是否已有业务语义;截断坐标轴会不会放大差异;数据口径在哪里查看。
如果一句话说不清“看完这张图下一步做什么”,它可能只是信息陈列。把这六个答案跟图表配置放在一起,后续换库或改样式时也不容易丢掉原始表达意图。