
本文介绍如何使用 chart.js 实现带目标值(60)的堆叠柱状图:底部显示当前实际值(蓝色),顶部叠加红色“缺口”柱子表示距离目标还差多少;若已达标,则红色部分高度为0。
本文介绍如何使用 chart.js 实现带目标值(60)的堆叠柱状图:底部显示当前实际值(蓝色),顶部叠加红色“缺口”柱子表示距离目标还差多少;若已达标,则红色部分高度为0。
在数据可视化中,直观呈现「完成度 vs 目标缺口」是项目管理、KPI 跟踪等场景的常见需求。Chart.js 本身不内置「目标线填充」功能,但可通过双数据集堆叠(stacked bar)+ 动态缺口计算优雅实现:一个数据集展示实际值(蓝色),另一个数据集展示 Math.max(0, 60 - actual)(红色),两者堆叠后总高度恒为 max(actual, 60),视觉上自然形成“达标即无红条”的效果。
✅ 实现步骤
- 准备原始数据(如各状态下的实际数值);
-
计算缺口值:对每个数据点,执行
Math.max(0, 60 - value),确保不出现负值; -
构建双数据集:
- 主数据集(蓝色):原始值;
- 缺口数据集(红色):计算所得缺口值;
-
启用堆叠模式:设置
scales.y.stacked = true,并指定datasets.stack = 'stack0'(Chart.js v3+ 推荐显式声明栈名)。
? 完整可运行示例(Chart.js v4+)
<div style="width: 500px; height: 300px;">
<canvas id="mychart"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4"></script>
<script>
(function() {
const ctx = document.getElementById("mychart").getContext('2d');
const rawValues = [10, 5, 80]; // Passed, Failed, In Progress
const target = 60;
// 计算缺口:仅当未达标时显示红色部分
const gapValues = rawValues.map(val => Math.max(0, target - val));
const config = {
type: 'bar',
data: {
labels: ['Passed', 'Failed', 'In Progress'],
datasets: [
{
label: 'Current Progress',
data: rawValues,
backgroundColor: 'rgba(54, 162, 235, 0.8)', // 蓝色
stack: 'stack0'
},
{
label: 'Remaining to Target (60)',
data: gapValues,
backgroundColor: 'rgba(255, 99, 132, 0.8)', // 红色
stack: 'stack0'
}
]
},
options: {
responsive: true,
scales: {
y: {
beginAtZero: true,
stacked: true, // 关键:启用Y轴堆叠
ticks: {
precision: 0 // 避免出现小数刻度
}
},
x: {
stacked: true
}
},
plugins: {
legend: {
position: 'top',
},
tooltip: {
callbacks: {
label: function(context) {
const label = context.dataset.label || '';
const value = context.parsed.y;
if (label.includes('Remaining')) {
return `${label}: ${value} to reach ${target}`;
}
return `${label}: ${value}`;
}
}
}
}
}
};
new Chart(ctx, config);
})();
</script>⚠️ 注意事项
-
版本兼容性:上述代码基于 Chart.js v4;若使用 v2/v3,请将
stacked: true改为stacked: true(v2/v3 中写在yAxes或y下),且无需显式stack属性(默认同名栈); -
零值处理:
Math.max(0, 60 - val)确保缺口永不为负,避免反向渲染异常; - 颜色语义:建议在图例和 Tooltip 中明确标注「Current Progress」与「Remaining to Target」,提升可读性;
-
扩展性:如需多目标(如不同类目不同目标值),可将
target改为数组,对应逐项计算。
通过该方案,你不仅能精准表达「已完成 vs 待完成」的对比关系,还能保持图表简洁专业,适用于仪表盘、进度看板等多种业务场景。


















