Chart.js 饼图与环形图实战:doughnut 定制、偏移与空状态处理
【免费下载链接】Chart.jsSimple HTML5 Charts using the项目地址: https://gitcode.com/gh_mirrors/ch/Chart.js
Chart.js 是一款基于 HTML5<canvas>标签的轻量级图表库,而饼图(pie)与环形图(doughnut)正是其中最受欢迎、上手最快的两种图表类型——它们天生适合展示"部分占整体"的比例关系。本文将带你快速掌握 doughnut 的定制技巧:如何调整中空比例、如何把某一块"拉出来"突出显示(offset 偏移)、以及在数据为空时如何优雅地处理空状态,让新手也能一步到位做出专业的占比图表。
一、pie 与 doughnut:同一个"类",只差一个参数
很多新手会疑惑:饼图和环形图为什么要写两份代码?
答案是:它们在 Chart.js 中其实是同一个控制器,仅在一个默认值上有区别——cutout(中间挖掉的空洞比例):
| 图表类型 | cutout默认值 | 效果 |
|---|---|---|
pie(饼图) | 0 | 实心圆 |
doughnut(环形图) | '50%' | 中间镂空,呈环状 |
其余配置、事件、动画逻辑完全一致。它们的默认值都定义在 controller.doughnut.js 中,而 pie 类型只是在 controller.pie.js 里克隆了这份默认值并把cutout改为0。
💡 实战建议:数据只有"占比"一个维度时用 pie;需要在中间放 KPI 数字、图标或标题时选 doughnut,信息密度更高。
二、五分钟上手:第一个环形图
一个最简环形图只需要labels(图例和提示框的文本)加一组data数值,Chart.js 会自动求和并计算每块弧长:
const data = { labels: ['Red', 'Blue', 'Yellow'], datasets: [{ label: 'My First Dataset', data: [300, 50, 100], backgroundColor: [ 'rgb(255, 99, 132)', 'rgb(54, 162, 235)', 'rgb(255, 205, 86)' ], hoverOffset: 4 // 鼠标悬停时该块向外弹出 4 像素 }] }; const config = { type: 'doughnut', data: data };把type改成'pie'就变成实心饼图,一行都不用动。完整示例可参考 docs/charts/doughnut.md 与 docs/samples/other-charts/doughnut.md。
三、doughnut 定制:cutout、radius、rotation 与 circumference
环形图有 4 个"骨架级"配置选项(均可写百分比字符串或像素数字):
| 选项 | 默认值 | 作用 |
|---|---|---|
cutout | '50%'(doughnut)/0(pie) | 中心空洞大小,可设为'80%'做出细窄的进度环 |
radius | '100%' | 图表外径 |
rotation | 0 | 第一块弧线从哪个角度开始画(0 = 正上方) |
circumference | 360 | 总扫过的角度,设为180即得到半环图 |
options: { cutout: '70%', // 细环 rotation: 90, // 从右侧 3 点钟方向开始 circumference: 270 // 只画 270 度,留一个缺口 }📌 小贴士:当circumference < 360时,Chart.js 会通过getRatioAndOffset()重新计算弧线的外包尺寸并自动居中,图形不会被裁切,这一点在源码 controller.doughnut.js 中可以找到。另外每块弧的圆角、虚线边框由borderRadius、borderDash、borderAlign('center'/'inner')控制,详见官方文档 docs/charts/doughnut.md。
四、offset 偏移实战:把某一块"弹出来"
想突出某一块数据?两个参数配合使用效果最好:
offset:静态偏移(像素),让指定弧块常驻"拉出"圆环之外。支持两种写法:- 数字:所有弧统一偏移,例如
offset: 10; - 数组:逐块指定,例如
offset: [0, 0, 30, 0, 0]—— 只有第 3 块被拉出,非常适合做"重点指标高亮"。
- 数字:所有弧统一偏移,例如
hoverOffset:悬停时的动态偏移(默认0),配合hoverBackgroundColor使用,鼠标划过哪块哪块就弹出,交互反馈非常直观。
Chart.js 在计算可用半径时会通过getMaxOffset()把所有offset/hoverOffset计入安全边距,所以拉出的弧块永远不会被画布边缘裁掉,这块逻辑在 controller.doughnut.js 中实现。
datasets: [{ data: [300, 50, 100], offset: [0, 0, 30], // 只把 Yellow 拉出来 hoverOffset: 4 // 其余块悬停时轻微弹出 }]对应的测试用例可以直接查看 test/fixtures/controller.doughnut/doughnut-offset.js,运行后能看到偏移弧块与圆环的视觉效果对比。
五、spacing 与 weight:间隙弧线与多层嵌套环
spacing+spacingMode:给所有弧块之间加固定像素间隙,形成"分段环"的视觉效果。spacingMode有三种模式:angular(默认):按角度均匀分配间隙;proportional:间隙随弧长等比缩放;parallel:间隙保持平行(两侧间距一致),视觉更整齐。
效果对比可参考 docs/samples/other-charts/ 目录下的 doughnut 示例与测试图 doughnut-spacing.png、doughnut-spacing-parallel.png。
weight:控制数据集的"环带粗细"。环形图支持多个数据集叠加,每个数据集是一个同心圆环,粗细按weight之和等比分配。官方示例 multi-series-pie.md 就用 4 组数据集 + 不同 weight 画出了"整体 vs 分组"的多层投票环。⚠️ 注意:多层环默认共用同一组角度,若每个数据集数值总和不同,弧段角度会错位;配合图例的
generateLabels自定义(示例中已给出写法)才能让图例与嵌套环一一对应。
六、空状态处理:用 afterDraw 插件画一个"占位环"
当接口还没返回数据、或筛选后data: []时,doughnut 默认只画一个空圆——看起来像渲染失败。官方给出的标准做法是写一个迷你插件,在afterDraw钩子里判断"是否真的没数据",然后在图表中央补画一个浅色圆环占位:
const plugin = { id: 'emptyDoughnut', afterDraw(chart, args, options) { const hasData = chart.data.datasets.some(d => d.data.length > 0); if (hasData) return; const {chartArea: {left, top, right, bottom}, ctx} = chart; const centerX = (left + right) / 2; const centerY = (top + bottom) / 2; const r = Math.min(right - left, bottom - top) / 2; ctx.beginPath(); ctx.lineWidth = options.width || 2; ctx.strokeStyle = options.color || 'rgba(255, 128, 0, 0.5)'; ctx.arc(centerX, centerY, r - (options.radiusDecrease || 0), 0, 2 * Math.PI); ctx.stroke(); } };插件的color、width、radiusDecrease都可以通过options.plugins.emptyDoughnut传参自定义,完整可运行版本见 docs/samples/plugins/doughnut-empty-state.md。
七、图例交互:点击隐藏某一块
doughnut 内置了贴心的图例交互:点击图例会调用toggleDataVisibility()隐藏对应的单块弧(而不是整个数据集),剩余的弧会自动重算角度填满整圆,非常适合做多条件筛选场景。这个默认行为定义在 controller.doughnut.js 的overrides中。若想按数据集整体隐藏/显示,可参考多层环示例中自定义onClick的写法(multi-series-pie.md)。
八、总结与扩展阅读
一句话回顾本文的 doughnut 定制清单:
- 选类型:
pie实心 /doughnut镂空,本质同一控制器,只差cutout; - 调骨架:
cutout、radius、rotation、circumference四个选项控制形态,半环图、细环图信手拈来; - 做高亮:
offset(支持数组逐块偏移)静态拉出 +hoverOffset悬停弹出; - 加细节:
spacing/spacingMode做间隙弧,weight做多层嵌套环; - 防尴尬:
afterDraw插件 + 占位圆环优雅处理空状态。
📚 延伸阅读(均为仓库内文件):
- 完整配置参考:docs/charts/doughnut.md
- 弧元素(arc element)底层实现:src/elements/element.arc.ts
- 官方可交互示例:docs/samples/other-charts/pie.md、docs/samples/other-charts/doughnut.md
- 行为测试用例(可当"活文档"看):test/fixtures/controller.doughnut/
【免费下载链接】Chart.jsSimple HTML5 Charts using the项目地址: https://gitcode.com/gh_mirrors/ch/Chart.js
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考