Chart
chart提供面积图、柱图、折线、饼图等常用图表,配色跟随主题
用法
面积图
data + series + xKey 三件套;多序列叠加,色彩走 chart token 自适应明暗。
tsx
<AreaChart
data={data}
series={[{ key: "revenue", label: "营收(千元)" }, { key: "orders", label: "订单" }]}
xKey="month"
/>折线 / 柱状
同一份数据可换 LineChart / BarChart 渲染。
tsx
<>
<LineChart data={data} series={series} xKey="month" />
<BarChart data={data} series={series} xKey="month" />
</>图例
多序列图不给图例,读者无从知道哪条线是哪条序列。legend 开一行色点(走 Dot 的 color,与序列色同源);"top" / "bottom" 选位置。height 仍是组件总高——画布相应变矮,不会把总高撑高。
营收(千元)订单
营收(千元)订单
tsx
<AreaChart data={data} series={series} xKey="month" legend />堆叠
stacked 让多序列堆叠(Area/Bar 生效)。
tsx
<BarChart data={data} series={series} xKey="month" stacked />横向柱状(CJK 类目自适应轴宽)
horizontal 把类目移到 Y 轴,轴宽默认按最长标签自适应(CJK 全角估宽,48–160px),不再截断中文;要精确控制传 yAxisWidth。
tsx
<BarChart
horizontal
data={[
{ stage: "音频解码", p50: 105 },
{ stage: "ASR识别", p50: 620 },
{ stage: "LLM首句", p50: 890 },
{ stage: "TTS首音", p50: 760 },
]}
xKey="stage"
series={[{ key: "p50", label: "P50 耗时(ms)" }]}
/>饼图 / 环形
扁平 {name,value} 数据;donut 中心挖空。
搜索直接社媒推荐
搜索直接社媒推荐
tsx
<>
<PieChart data={[{ name: "搜索", value: 420 }, { name: "直接", value: 280 }]} />
<PieChart donut data={[{ name: "搜索", value: 420 }, { name: "直接", value: 280 }]} />
</>双 Y 轴组合图
ComposedChart 让柱与线各吃一根值轴,量纲差几个数量级的两条序列才能同框(对标 echarts 双轴)。
营收(千元)订单
tsx
<ComposedChart
data={data}
xKey="month"
series={[
{ key: "revenue", label: "营收(千元)", type: "bar" },
{ key: "orders", label: "订单", type: "line", axis: "right" },
]}
leftAxisLabel="营收(千元)"
rightAxisLabel="订单"
legend
/>参考线
referenceLines 画目标线/均值线/帕累托的 80 线(对标 echarts markLine)。
tsx
<BarChart
data={data}
series={[{ key: "revenue", label: "营收(千元)" }]}
xKey="month"
referenceLines={[{ y: 100, label: "目标" }]}
/>雷达图
多维能力对比,xKey 为维度字段,多序列叠加。
当前基准
tsx
<RadarChart
data={radarData}
series={[{ key: "当前" }, { key: "基准" }]}
xKey="dim"
/>逐轴满量程的雷达图
axisMax 给每根角轴各配一个满量程,量纲差三个数量级也能比形状;tooltip 仍显示原始值。
湖滨店新街口店
tsx
<RadarChart
data={dims}
series={[{ key: "hubin", label: "湖滨店" }, { key: "xinjiekou", label: "新街口店" }]}
xKey="dim"
axisMax={{ 销售额: 500000, 订单数: 800, 客单价: 600, 会员数: 4000, 退货率: 100 }}
/>何时用
仪表盘里画趋势/分布/对比图(面积、柱、线、饼、环、雷达、径向),自动套瑚琏 chart token 配色。要展示单个 KPI 数字用 Stat/Statistic;要轻量内联趋势走 [Sparkline];本组件是完整的多序列坐标图,基于 recharts。
导入
ts
import { AreaChart, BarChart, ComposedChart, LineChart, PieChart, RadarChart, RadialChart, chartColor } from "@hulianui/ui"Props
AreaChart / BarChart / LineChart / ComposedChart / RadarChart(笛卡尔类)
| 名称 | 类型 | 默认 | 说明 |
|---|---|---|---|
| data* | TDatum[] | - | 行数据数组 |
| series* | ChartSeries[] | - | 序列定义 { key, label?, color? };color 缺省按 index 取 var(--color-chart-N),可传语义色名/CSS 颜色覆盖 |
| xKey* | string | - | 横轴字段名 |
| height | number | 280 | 高度(SSR 安全:宽走 ResponsiveContainer,高需显式值) |
| stacked | boolean | false | 多序列堆叠(Area/Bar 生效) |
| legend | boolean | "top" | "bottom" | false(Radar 为 true) | 序列图例(色点 + label)。true 等价 "bottom",false 关掉。色点走 Dot 的 color,与序列色同源。默认值按图种分两档:笛卡尔三件默认关,Radar 默认开(历来自带图例,保持零改动) |
| legendScroll | boolean | false | 图例恒为单行 + 横向滚动(对齐 echarts legend.type: "scroll")。缺省是换行居中,序列一多就堆成多行挤扁画布;序列 >8 条开这个 |
| horizontal | boolean | false | BarChart 专属:横向柱状 |
| yAxisWidth | number | 自适应 | BarChart 专属:horizontal 类目轴宽 px;默认按最长标签自适应(CJK 全角估宽·48-160,纯函数 categoryAxisWidth 可测),超长标签或精确控制时显式传 |
| radiusAxis | boolean | true | RadarChart 专属:半径轴的刻度数字(0 15 30 …)。传 false 只留环线与角轴名,即 echarts radar 的默认形态(它的 axisLabel.show 默认就是 false)。如果你的雷达图序列较多或数据填得满,建议关掉——见下方注意事项 |
| onPointClick | (info: { datum, index, seriesKey? }) => void | - | 数据点点击(对标 echarts 的 chart.on('click'),用于钻取)。命中判据与 tooltip 同源:tooltip 亮了点下去就一定有回调,不必精确点中 2px 的折线;点在画布空白或坐标轴上不触发。seriesKey 不保证有值(共享 tooltip 时 recharts 不认为某一条序列被单独命中)。RadarChart 没有这个 prop |
| referenceLines | ChartReferenceLine[] | - | 值轴参考线(对标 echarts 的 markLine):帕累托的 80/95 线、均值线、目标线。见下方 ChartReferenceLine 表。RadarChart 没有这个 prop |
| yAxisDomain | [number | "auto", number | "auto"] | 自适应 | 值轴显示范围 [min, max],"auto" 表示该端仍按数据自适应(对标 echarts 的 yAxis.min/max)。典型场景是百分比轴锁 [0, 100]:auto 会把「82%」画到顶格读成快满,且越界的 referenceLines 会被静默丢弃不画。数据超出锁定范围时轴会扩大容纳(不裁剪路径)。horizontal 柱图的值轴是横轴,同样由它管。ComposedChart 用 `leftAxisDomain`/`rightAxisDomain` 代替;RadarChart 没有这个 prop |
| series[].type | "bar" | "line" | "area" | "bar" | ComposedChart 专属:该序列画成什么 |
| series[].axis | "left" | "right" | "left" | ComposedChart 专属:该序列吃哪根值轴 |
| leftAxisLabel / rightAxisLabel | string | - | ComposedChart 专属:轴标题。左右各画各的量纲时不标名字,读者分不出哪条线读哪根轴 |
| leftAxisDomain / rightAxisDomain | [number | "auto", number | "auto"] | 自适应 | ComposedChart 专属:逐轴 domain,语义同 yAxisDomain。右轴的第一大用户是百分比轴(帕累托累计占比、退货率、达成率),锁 rightAxisDomain={[0, 100]} 满量程后,referenceLines={[{ y: 95, axis: "right" }]} 不再因越界被丢弃 |
| axisMax | Record<string, number> | - | RadarChart 专属:每根角轴各自的满量程,键是角轴维度值。见下方「量纲差很多的雷达图」 |
| className | string | - | 透传类名(宽度在此设,如 w-[32rem]) |
PieChart / RadialChart(扁平数据类)
| 名称 | 类型 | 默认 | 说明 |
|---|---|---|---|
| data* | ChartDatum[] | - | 扁平数据点 { name, value, color? } |
| donut | boolean | false | PieChart:环形图(中心挖空) |
| height | number | 280 | 高度 |
| legend | boolean | "top" | "bottom" | true | 图例(色点 + data[].name),语义同上但默认开(这两件历来自带图例)。传 false 关掉——自绘图例时必须关,否则两份图例并排 |
| legendScroll | boolean | false | 同上:图例恒为单行 + 横向滚动 |
| onPointClick | (info: { datum, index }) => void | - | 点中某一片时回调(钻取用)。扇区级命中,点在留白处不触发 |
| className | string | - | 透传类名 |
ChartReferenceLine
| 名称 | 类型 | 默认 | 说明 |
|---|---|---|---|
| y* | number | - | 值轴上的位置 |
| label | string | - | 线上文案(如「80%」「目标」) |
| axis | "left" | "right" | "left" | 挂在哪根值轴上,仅 ComposedChart 有意义 |
| color | string | --color-muted-foreground | 线色。缺省刻意不取 chart-N:它不是一条数据,抢了序列的色相会被读成「第 N 条序列」 |
| dash | string | "4 4" | 虚线段样式,传空串即实线 |
禁忌 / 坑
- 宽度交给父容器 / className,高度必须显式(
height默认 280)——宽走 ResponsiveContainer 但高拿不到会塌成 0。 - 在收缩的 flex 容器里 ResponsiveContainer 可能量不到宽,需给容器显式宽度,见 [[recharts-responsive-container-needs-explicit-width-in-shrink-flex]]。
- headless 截图常出现「只剩坐标轴、数据区空白」——不是 bug,是入场动画的 clipPath 被 rAF 饿死,设
prefers-reduced-motion: reduce再截即显,见 [[recharts-headless-screenshot-blank-clippath-animation-starved]]。 - horizontal 类目轴宽自适应有 160px 上限(防超长标签吃掉图区)——类目 >12 个全角字仍会截断,此时消费侧截短标签或显式传
yAxisWidth。 legend开启后height仍是组件总高:图例占一行,画布相应变矮,不会把总高撑高。序列多到换行时图例会堆成多行、继续挤压画布——这时候不要靠调大 `height` 硬扛(28 条序列的图例是 5 行,把雷达盘撑回可读尺寸得把总高翻倍),开legendScroll让图例恒为单行横滚。- 极坐标三件(Pie/Radar/Radial)的
legend默认是 `true`,与笛卡尔三件相反——它们历来自带图例,改默认会破坏存量版式。自绘图例前先legend={false},否则两份图例并排。 - 自绘图例时色点用
<Dot color={...} />,不要写<Dot style={{ color }} />——那是静默失效(圆点是背景色),见 Dot 的坑。 - RadarChart 的半径轴刻度(
radiusAxis,默认开)画在数据区里而不是外面:刻度锚点沿一条水平半径均匀排开,正好从雷达盘中心穿到边缘,而且每个数字被 recharts 旋转 90° 竖排。序列一多、数据填得满,前几个刻度就整个落在数据多边形内部,既压住图形又难读。这一条看版式是发现不了「选错了」的——图能正常渲染,只是糊在一起。多序列雷达图建议直接radiusAxis={false}:雷达图读的是形状对比,精确取值有 tooltip。
相关
Stat · Statistic · Meter · Timeline · NumberTicker · WorldMap
Playground
<AreaChart data={series} series={[{ key: "revenue" }, { key: "orders" }]} xKey="month" />