Appearance
图表 Charts
x-next 内置一套手写 SVG 图表,无外部图表库依赖:颜色跟随 --x-color-* token 联动主题与换主色,交互与组件库其余部分一致(受控、插槽、无障碍)。
覆盖 AI 面板与后台系统里最常用的五类基础图表;复杂图表(K 线 / 桑基 / 关系图 / 地图 / 甘特 / 3D)请在业务侧接入 ECharts 等专业库,不要期望用这里的组件硬拼。
怎么选
| 要看什么 | 用哪个 | 说明 |
|---|---|---|
| 随时间的变化趋势(Token、成本、请求量) | LineChart 折线图 | 主图首选。多系列对比、面积填充、堆叠面积 |
| 按类目比较大小(各接口耗时、各渠道量) | BarChart 柱状趋势图 | 单系列看趋势,多系列并排或堆叠看构成 |
| 看占比构成(模型占比、渠道占比) | PieChart 饼图 | 建议用环形 + 中心合计;类别超过 7 个改用堆叠柱 |
| 卡片角落的迷你走势 | TrendChart 迷你趋势图 | 无坐标轴、无图例,纯形态提示;高度控制在 40~60px、宽度 100~320px |
| 活跃度分布(按天 / 周) | Heatmap 热力图 | 一年或任意区间的密度分布 |
选择时的三个判断
- 要读数还是看形态? 需要坐标轴读数、悬浮明细、多系列对比,用 LineChart / BarChart / PieChart;只需要「大致在涨还是跌」,用 TrendChart。
- 是趋势还是构成? 时间轴上比较用折线;类目间比较用柱状;占比用环形。别用饼图做趋势,也别用折线表达静态构成。
- 类目有多少? 折线与柱状在 30+ 类目下仍然可读(x 轴标签会自动抽稀);饼图超过 7 个分片就该换堆叠柱状,角度比长度更难分辨。
五个组件的分工
| 组件 | 数据模型 | 坐标轴 | 典型高度 |
|---|---|---|---|
| LineChart | series[{ name, data }] + categories | 类目轴 + 数值轴(支持负值) | 240 ~ 320 |
| BarChart | series[{ name, data }] + categories | 类目轴 + 数值轴(0 基线) | 240 ~ 320 |
| PieChart | data[{ name, value }] | 无 | 200 ~ 300 |
| TrendChart | dataset: number[] | 无 | 40 ~ 60 |
| Heatmap | data[{ timestamp, value }] | 无 | 按格子尺寸 |
共同约定
- 尺寸:
height传数字按 px(默认 240 ~ 280),width默认撑满父容器;容器尺寸变化时自动重算几何与标签抽稀。 - 提示:默认开启,整块画布只挂一个提示节点(不是每个数据点一个浮层),支持
tooltip插槽完全自定义。 - 图例:
legend开启后点击项可临时隐藏对应系列 / 分片,并触发legend-change;数值轴会按剩余可见系列重算。 - 键盘与读屏:画布可聚焦,方向键移动读数,Home / End 跳首尾,Esc 关闭;键盘导航时通过
aria-live播报,ariaLabel提供图像名称。 - 缺测:BarChart 与 PieChart 把
null/ 负数按 0 处理(不画柱、不计入占比);LineChart 默认在缺测处断开,可用connectNulls改为跨过连接。 - 按需引入:图表族共享一层样式,按需引入时需要同时引
base.css与对应组件样式。
ts
import { createApp } from 'vue';
import { LineChart } from 'x-next';
import 'x-next/style/base.css';
import 'x-next/style/line-chart.css';
createApp(App).use(LineChart);组合示例
同一个面板里组合折线与柱状:把数量放柱状、比率放折线,共用同一组 categories。
vue
<template>
<x-line-chart
:categories="categories"
:series="series"
legend
area
:height="260"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const categories = ref(['周一', '周二', '周三', '周四', '周五', '周六', '周日']);
const series = ref([
{ name: '请求量', data: [820, 932, 901, 934, 1290, 1330, 1320] },
{ name: '错误数', data: [120, 132, 101, 134, 90, 230, 210] },
]);
</script>