
本文详解如何在 chart.js 饼图中使用 chartjs-plugin-datalabels 插件,将图内标签和悬停提示从默认的原始计数(count)切换为百分比(%),涵盖数据预处理、插件配置及常见陷阱规避。
要在 Chart.js 饼图中正确显示百分比(而非原始数值),不能仅靠修改数据数组为百分比值——这虽能改变图内数字,但会导致悬停提示(tooltip)仍显示原始值,且饼图扇区面积会按错误比例渲染(因 Chart.js 依据 data 值计算角度)。因此,必须双管齐下:
- 保持原始数据用于图表计算(确保扇区大小准确);
- 通过插件配置动态生成并显示百分比标签。
以下是推荐的、健壮且符合 Chart.js 最佳实践的实现方式:
✅ 正确做法:保留原始数据 + 自定义 datalabels.formatter
const totalLabels = ["HD", "SKY"];
const totalData = [138, 251]; // 注意:改为数字类型,非字符串
// 计算总和(用于百分比计算)
const totalSum = totalData.reduce((a, b) => a + b, 0);
const ctx = document.getElementById('totalChart').getContext('2d');
new Chart(ctx, {
type: 'pie',
data: {
labels: totalLabels,
datasets: [{
label: 'No of Leads',
data: totalData, // ✅ 保持原始数值 —— 决定扇区大小
borderWidth: 1,
backgroundColor: ['#4e73df', '#1cc88a'] // 可选:增强可读性
}]
},
options: {
responsive: true,
plugins: {
tooltip: {
// ✅ 自定义悬停提示,显示百分比
callbacks: {
label: function(context) {
const value = context.raw;
const percentage = ((value / totalSum) * 100).toFixed(1);
return `${context.label}: ${value} (${percentage}%)`;
}
}
},
datalabels: {
// ✅ 核心:图内标签显示百分比
formatter: function(value, context) {
const dataset = context.dataset;
const total = dataset.data.reduce((a, b) => a + b, 0);
const percentage = ((value / total) * 100).toFixed(1);
return `${percentage}%`;
},
color: '#fff',
font: {
weight: 'bold'
},
padding: 6
}
}
}
});⚠️ 关键注意事项
- 数据类型必须为数字:totalData = ["138","251"] 是字符串数组,reduce 会拼接成 "138251"。务必写成 [138, 251]。
- 不要篡改 data 数组为百分比:如 data: totalData.map(...) 会导致扇区角度错误(Chart.js 将 13.8% 当作 13.8 的绝对值绘图)。
- datalabels.formatter 是核心:它接收每个扇区的原始值(value)和上下文,可安全访问 dataset.data 计算实时百分比。
- tooltip.callbacks.label 提升用户体验:让用户同时看到原始值与百分比,信息更完整。
- 动态数据兼容性:上述 reduce 计算在每次 formatter 调用时执行,天然支持动态更新的数据集。
? 进阶提示(可选)
若需全局复用百分比逻辑,可封装为工具函数:
const getPercentage = (value, dataset) => ((value / dataset.data.reduce((a, b) => a + b, 0)) * 100).toFixed(1) + '%'; // 在 formatter 中调用: formatter: (value, ctx) => getPercentage(value, ctx.dataset)
通过以上配置,你的饼图将精准呈现:扇区大小基于真实数据量,图内标签清晰显示百分比,悬停提示同时展示数值与占比——专业、准确、用户友好。










