Skip to content

图表 Charts ​

x-next 内置一套手写 SVG 图表,无外部图表库依赖:颜色跟随 --x-color-* token 联动主题与换主色,交互与组件库其余部分一致(受控、插槽、无障碍)。

覆盖 AI 面板与后台系统里最常用的五类基础图表;复杂图表(K 线 / 桑基 / 关系图 / 地图 / 甘特 / 3D)请在业务侧接入 ECharts 等专业库,不要期望用这里的组件硬拼。

怎么选 ​

要看什么用哪个说明
随时间的变化趋势(Token、成本、请求量)LineChart 折线图主图首选。多系列对比、面积填充、堆叠面积
按类目比较大小(各接口耗时、各渠道量)BarChart 柱状趋势图单系列看趋势,多系列并排或堆叠看构成
看占比构成(模型占比、渠道占比)PieChart 饼图建议用环形 + 中心合计;类别超过 7 个改用堆叠柱
卡片角落的迷你走势TrendChart 迷你趋势图无坐标轴、无图例,纯形态提示;高度控制在 40~60px、宽度 100~320px
活跃度分布(按天 / 周)Heatmap 热力图一年或任意区间的密度分布

选择时的三个判断 ​

  1. 要读数还是看形态? 需要坐标轴读数、悬浮明细、多系列对比,用 LineChart / BarChart / PieChart;只需要「大致在涨还是跌」,用 TrendChart。
  2. 是趋势还是构成? 时间轴上比较用折线;类目间比较用柱状;占比用环形。别用饼图做趋势,也别用折线表达静态构成。
  3. 类目有多少? 折线与柱状在 30+ 类目下仍然可读(x 轴标签会自动抽稀);饼图超过 7 个分片就该换堆叠柱状,角度比长度更难分辨。

五个组件的分工 ​

组件数据模型坐标轴典型高度
LineChartseries[{ name, data }] + categories类目轴 + 数值轴(支持负值)240 ~ 320
BarChartseries[{ name, data }] + categories类目轴 + 数值轴(0 基线)240 ~ 320
PieChartdata[{ name, value }]无200 ~ 300
TrendChartdataset: number[]无40 ~ 60
Heatmapdata[{ 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>