数据可视化组件
选图表类型、编码感知、带视觉摘要的无障碍数据表。
组件模式高级
为什么
错图表类型说谎:12 片饼图不可读、分类数据用折线暗示假趋势。按数据类型和问题选图表使可视化回答问题而非提出新问题。
复合组件模式被 Radix UI、Headless UI 和 shadcn/ui 采用 — 这是 2024 年采用最多的三个无头库。相比扁平组件 API,它们减少 70% 的属性逐层传递。
何时使用
用户需比较值、看分布或跟踪趋势时建可视化。始终旁提供数据表视图 — 可视化是摘要,表是真相。
如何做
1. 图表匹配问题 — 比较分类→柱、部分占整体→堆叠柱(非饼)、随时间趋势→折线、分布→直方图
2. 编码感知 — 长度(柱)最准,次位置,再角度/面积/色;避免 >5 片饼图
3. 库 — Recharts/Victory(React,SVG)简单;D3 自定义;ECharts 重交互
4. 无障碍 — 每图有数据表切换、SVG 上 aria-label、role="img" 带文本摘要
5. 颜色 — 绝非唯一编码(色盲用户);色配图案或直接标签
6. 响应式 — SVG 带 viewBox 缩放;或用容器查询窄视口时柱→列切换
7. 性能 — >1 万点降采样、缩放时抽稀、大数据集渲染 canvas 非 SVG
示例
import { BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer } from "recharts";
function RevenueChart({ data }: { data: { month: string; revenue: number }[] }) {
return (
<figure role="img" aria-label="月收入柱状图">
<figcaption className="sr-only">
按月收入:{data.map((d) => `${d.month} ${d.revenue}`).join(",")}
</figcaption>
<ResponsiveContainer width="100%" height={300}>
<BarChart data={data}>
<XAxis dataKey="month" />
<YAxis />
<Tooltip />
<Bar dataKey="revenue" fill="var(--color-action-primary)" radius={[4, 4, 0, 0]} />
</BarChart>
</ResponsiveContainer>
<details className="mt-2"><summary>查看数据表</summary>
<table><tbody>{data.map((d) => <tr key={d.month}><td>{d.month}</td><td>{d.revenue}</td></tr>)}</tbody></table>
</details>
</figure>
);
}
常见问题
- ⚠12 片饼图 — 用户无法比较片角度,图例干所有活
- ⚠颜色作唯一编码 — 红绿状态点对色盲用户不可见
- ⚠无数据表回退 — 屏幕阅读器见无语义 SVG,数据不可达
最佳实践
- ✓图表匹配问题 — 柱比较、折线趋势、绝不用 >5 片饼图
- ✓始终图表配数据表 — 可视化摘要,表是无障碍真源
- ✓先用长度/位置编码、最后颜色 — 且绝不仅色,配标签或图案