如何使用Chart.js实现单药物多状态分段柱状图并解决标签与圆角问题?
针对Chart.js柱状图两个问题的解决方案
1. 同一药物多段记录添加统一顶部标签
通过自定义Chart.js插件就能实现,核心是按药物名称分组柱子,计算每组的中心位置后绘制统一标签。
示例代码:
const drugLabelPlugin = { id: 'drugLabel', afterDatasetsDraw(chart) { const ctx = chart.ctx; ctx.save(); ctx.font = '14px Arial'; ctx.fillStyle = '#333'; ctx.textAlign = 'center'; ctx.textBaseline = 'bottom'; // 按药物名称分组所有柱子 const drugGroups = {}; chart.data.datasets.forEach((dataset) => { dataset.data.forEach((_, index) => { const drugName = dataset.label; // 假设dataset的label为药物名称 if (!drugGroups[drugName]) drugGroups[drugName] = []; const bar = chart.getDatasetMeta(dataset.index).data[index]; drugGroups[drugName].push(bar); }); }); // 绘制每组的顶部标签 Object.values(drugGroups).forEach(group => { const firstBar = group[0]; const lastBar = group[group.length - 1]; // 计算整个药物分段的中心X坐标 const centerX = (firstBar.x - firstBar.width/2 + lastBar.x + lastBar.width/2) / 2; const labelY = firstBar.y - 10; // 标签距离柱子顶部10px ctx.fillText(group[0]._dataset.label, centerX, labelY); }); ctx.restore(); } }; // 注册插件 Chart.register(drugLabelPlugin);
如果药物名称不是存在dataset.label中,只需调整分组的判断字段即可。
2. 多段记录的整体圆角效果
默认borderRadius会给每个独立柱子加圆角,要实现整体圆角,需自定义柱子绘制逻辑,判断当前柱子是同一药物的首段、末段还是中间段,只保留对应方向的圆角:
示例代码:
const roundedGroupBarPlugin = { id: 'roundedGroupBar', beforeDraw(chart) { const datasets = chart.data.datasets; datasets.forEach((mainDs) => { const drugName = mainDs.label; // 收集同一药物的所有柱子信息 const sameDrugBars = []; datasets.forEach((ds, dsIdx) => { if (ds.label === drugName) { ds.data.forEach((_, dataIdx) => { const bar = chart.getDatasetMeta(dsIdx).data[dataIdx]; sameDrugBars.push({bar, dsIdx, dataIdx}); }); } }); // 按X轴位置排序(确保时间顺序正确) sameDrugBars.sort((a, b) => a.bar.x - b.bar.x); // 为每个柱子设置对应圆角 sameDrugBars.forEach((item, idx) => { const bar = item.bar; if (idx === 0) { // 首段:仅保留左圆角 bar.borderRadius = {topLeft: 8, bottomLeft: 8, topRight: 0, bottomRight: 0}; } else if (idx === sameDrugBars.length - 1) { // 末段:仅保留右圆角 bar.borderRadius = {topLeft: 0, bottomLeft: 0, topRight: 8, bottomRight: 8}; } else { // 中间段:无圆角 bar.borderRadius = 0; } }); }); } }; // 注册插件 Chart.register(roundedGroupBarPlugin);
可自行修改8调整圆角大小,注意确保数据按时间顺序排列,或在插件排序逻辑中正确识别前后段。
额外提示
- 两个插件可同时注册使用,互不冲突
- 若你的数据结构和示例不同,只需对应调整分组、排序的判断逻辑
- 测试时可单独启用一个插件,验证效果后再组合使用
内容的提问来源于stack exchange,提问作者Thomas99
相关产品推荐
相关产品推荐

