zan-charts
v0.1.6
Published
Lightweight charts core for Zan ecosystem
Readme
zan-charts
轻量级业务图表核心库,面向浏览器端快速生成 SVG 图表。当前支持柱状图、折线图、面积图、组合图和饼图/环形图。
适用范围
- 后台看板、统计卡片、趋势图、对比图
- 需要轻量 SVG 输出、导出 PNG/SVG、共享 tooltip、缩放和图例联动的场景
- 希望用统一数据结构覆盖
bar / line / area / combo / pie
不适合:
- 3D 图表、地理图、大规模实时流图
- 强依赖浏览器外渲染上下文的复杂动画图
安装
npm install zan-charts快速开始
import { createChart } from 'zan-charts'
const container = document.getElementById('chart') as HTMLElement
const chart = createChart(container, {
type: 'combo',
title: '销售趋势',
categoryField: 'month',
series: [
{ field: 'sales', label: '销售额', type: 'bar', stack: 'amount', showLabel: true },
{ field: 'profit', label: '利润', type: 'line', yAxisIndex: 1, smooth: true }
],
data: [
{ month: '1月', sales: 120, profit: 35 },
{ month: '2月', sales: 150, profit: 42 }
],
yAxes: [
{ name: '销售额' },
{ name: '利润率', formatter: value => `${value}%` }
],
referenceLines: [{ value: 140, label: '目标值' }],
referenceAreas: [{ start: 100, end: 160, label: '合理区间' }],
enableZoom: true,
tooltip: {
shared: true,
crosshair: true
},
toolbar: {
enabled: true,
showResetZoom: true,
showExportPng: true,
showExportSvg: true
}
})
chart.update({
data: [
{ month: '3月', sales: 180, profit: 56 }
]
})数据模型
1. categoryField
- 笛卡尔坐标图的类目轴字段
- 也是 tooltip、点击事件、缩放窗口的主轴索引来源
2. series
每个序列至少需要:
field:值字段label:图例和 tooltip 文案
可选能力:
type:bar | line | areastack:同组堆叠smooth:平滑折线showSymbol:折线点位showLabel:数据标签yAxisIndex:绑定主轴或副轴labelFormatter:标签格式化
3. data
[
{ month: '1月', sales: 120, profit: 35 },
{ month: '2月', sales: 150, profit: 42 }
]- 每行对应一个类目
series.field必须能在data行上取到值
图表类型
bar
- 默认纵向柱图
- 适合销量、次数、金额等离散对比
line
- 适合趋势、监控、连续变化
- 可配
smooth、showSymbol
area
- 本质是带填充的折线
- 适合强调体量变化和区间感
combo
- 允许不同序列混用
bar / line / area - 常用于“销量 + 转化率”“金额 + 占比”一类双指标图
pie
推荐使用“单条数据 + 多个 series 字段”的结构:
createChart(container, {
type: 'pie',
title: '作息分布',
categoryField: 'bucket',
series: [
{ field: 'study', label: '学习' },
{ field: 'work', label: '工作' },
{ field: 'rest', label: '休息' },
{ field: 'entertainment', label: '娱乐' }
],
data: [
{
bucket: 'today',
study: 20,
work: 40,
rest: 30,
entertainment: 10
}
],
pie: {
donut: true,
totalLabel: '总计',
showSliceLabels: true,
valueFormatter: value => `${value}%`
}
})核心配置
ZanChartOptions 的关键字段:
type:图表类型,默认bartitle:标题categoryField:类目字段,必填series:序列定义,必填data:数据数组,必填width/height:固定尺寸autoFit:是否自适应容器margins:边距theme:颜色与主题变量orientation:vertical | horizontalshowLegend:是否显示图例hiddenSeries:默认隐藏的序列字段enableZoom/zoomWindow:缩放配置xAxisFormatter/yAxisFormatter:坐标轴格式化yAxes:双轴配置referenceLines/referenceAreas:参考线与参考区间emptyState:空态文案tooltip:tooltip 配置pie:饼图/环形图配置toolbar:导出与重置缩放hooks:交互回调
常见能力
双 Y 轴
yAxes: [
{ name: '销售额' },
{ name: '利润率', formatter: value => `${value}%` }
],
series: [
{ field: 'sales', label: '销售额', type: 'bar', yAxisIndex: 0 },
{ field: 'profitRate', label: '利润率', type: 'line', yAxisIndex: 1 }
]缩放
enableZoom: true,
zoomWindow: {
startIndex: 0,
endIndex: 11
}适用:
- 时间序列
- 周期性长列表趋势图
参考线 / 参考区间
referenceLines: [
{ value: 100, label: '目标值', color: '#ef4444', lineDash: '4 2' }
],
referenceAreas: [
{ start: 80, end: 120, label: '健康区间', color: '#10b981', opacity: 0.12 }
]工具栏和导出
toolbar: {
enabled: true,
showResetZoom: true,
showExportPng: true,
showExportSvg: true,
pngFilename: 'sales-chart.png',
svgFilename: 'sales-chart.svg'
}空态
emptyState: {
text: '暂无数据',
subtext: '请调整筛选条件后重试'
}Tooltip
tooltip.formatter 支持返回 HTML 字符串,并按不同触发场景提供不同上下文。
共享 tooltip
tooltip: {
shared: true,
crosshair: true,
formatter: context => {
if (context.trigger !== 'shared') {
return ''
}
return `
<div style="font-weight:600;margin-bottom:6px">${context.category}</div>
${context.points.map(point => `<div>${point.label}: ${point.formattedValue}</div>`).join('')}
`
}
}饼图 tooltip
tooltip: {
formatter: context => {
if (context.trigger === 'item' && context.chartType === 'pie') {
return `<strong>${context.label}</strong><br />${context.formattedValue} / ${context.percentageLabel}`
}
return `${context.label}: ${context.formattedValue}`
}
}Hooks
hooks: {
onLegendToggle: (field, visible) => {
console.log('legend toggle', field, visible)
},
onZoomChange: (startIndex, endIndex) => {
console.log('zoom', startIndex, endIndex)
},
onPointClick: payload => {
console.log(payload.category, payload.field, payload.value)
}
}适用场景:
- 图例控制外部统计卡
- 缩放联动外部筛选
- 点击点位打开详情弹层
Handle API
createChart(container, options) 返回 ZanChartHandle:
update(partialOptions):局部更新配置或数据resetZoom():重置缩放窗口toSvgString():导出 SVG 字符串toDataUrl(type?):导出data URLdownload(filename?, type?):下载 PNG 或 SVGdestroy():销毁图表
低层能力
除 createChart() 外,还导出了两个偏底层的方法:
buildChartModel:把输入配置转成标准化图表模型,适合测试、预计算、调试renderChartSvg:把图表模型直接渲染成 SVG 字符串,适合快照、服务端拼装、导出链路
使用建议
- 优先保证容器尺寸稳定,再开启
autoFit pie图只推荐单行数据结构,多行数据不属于当前主线设计- 组合图请显式写
series.type,不要完全依赖默认推断 - 如果某个字段是百分比,展示格式化放在
formatter,原始数据尽量仍保留数值
边界与限制
- 当前是浏览器端 SVG 图表,不是 Canvas/WebGL 图表
- 不提供地理图、关系图、桑基图等复杂专用图
createChart依赖真实 DOM 容器,SSR 需自行规避挂载时机
开发命令
npm run test
npm run build