Chart.js水平条形图无法修改条形宽度的技术求助
Chart.js水平条形图:自定义条形宽度+独立图例解决方案
问题描述
用Chart.js实现水平条形图时遇到两个核心问题:
- 无法调整条形的宽度
- 若将所有数据合并到单个数据集,无法为每个Y轴条目显示独立颜色的图例
为实现Y轴每个条目对应独立图例,我采用了每个分类单独创建数据集的方式,格式如下:
data: [99, null, null, null, null, null, null, null, null],
以下是原始实现代码:
原始JavaScript代码
var chrt = document.getElementById("chartId").getContext("2d"); var chartId = new Chart(chrt, { type: 'Capacity', // 无效配置,会被下一行覆盖 type: 'bar', data: { labels: ["Amkor-FJ", "ASE-CL", "ASE-KH", "ATMC", "Global7", "SSMC", "TSMC8", "TSTSTAT", "UMCF8E"], datasets: [ { label: "Amkor-FJ", data: [99, null, null, null, null, null, null, null, null], backgroundColor: "yellow", borderColor: 'yellow', borderWidth: 1, }, { label: "ASE-CL", data: [null, 97, null, null, null, null, null, null, null], backgroundColor: "yellow", borderColor: 'yellow', borderWidth: 1, }, { label: "ASE-KH", data: [null, null, 100, null, null, null, null, null, null], backgroundColor: "red", borderColor: 'red', borderWidth: 1, }, { label: "ATMC", data: [null, null, null, 110, null, null, null, null, null], backgroundColor: "red", borderColor: 'red', borderWidth: 1, }, { label: "Global7", data: [null, null, null, null, 105, null, null, null, null], backgroundColor: "red", borderColor: 'red', borderWidth: 1, }, { label: "SSMC", data: [null, null, null, null, null, 87, null, null, null], backgroundColor: "green", borderColor: 'green', borderWidth: 1, }, { label: "TSMC8", data: [null, null, null, null, null, null, 85, null, null], backgroundColor: "green", borderColor: 'green', borderWidth: 1, }, { label: "TSTSTAT", data: [null, null, null, null, null, null, null, 100, null], backgroundColor: "yellow", borderColor: 'yellow', borderWidth: 1, }, { label: "UMCF8E", data: [null, null, null, null, null, null, null, null, 92], backgroundColor: "green", borderColor: 'green', borderWidth: 1, }, ], }, options: { indexAxis: 'y', elements: { bar: { borderWidth: 2, } }, plugins: { legend: { display: true, position: "bottom", align: "left" } }, legend: { // 重复配置,3.x版本应放在plugins.legend下 labels: { boxWidth: 1 } }, scales: { yAxes: [{ // 3.x版本已废弃该写法,改用scales.y categorySpacing: 0, barThickness : 73 }], x: { beginAtZero: true, ticks: { callback: function (value) { return (value / 100 * 100).toFixed(0) + '%'; }, }, scaleLabel: { display: true, labelString: 'Percentage', }, } } } });
原始HTML代码
<div style="display:inline-block; width:400px; height:400px"> <canvas id="chartId" aria-label="chart" width="350px" height="300px"></canvas> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.1.1/chart.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/chart.min.js"></script> <!-- 版本冲突,需移除 -->
解决方案
核心修复点
- 移除版本冲突:只保留一个Chart.js版本(推荐3.x,语法更统一)
- 统一配置语法:使用3.x版本的配置规则,废弃2.x的
yAxes写法 - 优化数据集结构:用单个数据集+颜色数组替代多数据集,简化代码
- 自定义图例生成:通过插件实现每个Y轴条目的独立图例,支持点击控制显示隐藏
- 正确设置条形宽度:在
scales.y中配置barThickness和categorySpacing
修改后的完整代码
JavaScript代码
var chrt = document.getElementById("chartId").getContext("2d"); // 定义每个条目的颜色,与labels顺序对应 const barColors = [ "yellow", "yellow", "red", "red", "red", "green", "green", "yellow", "green" ]; var chartId = new Chart(chrt, { type: 'bar', data: { labels: ["Amkor-FJ", "ASE-CL", "ASE-KH", "ATMC", "Global7", "SSMC", "TSMC8", "TSTSTAT", "UMCF8E"], datasets: [{ data: [99, 97, 100, 110, 105, 87, 85, 100, 92], backgroundColor: barColors, borderColor: barColors, borderWidth: 1, }] }, options: { indexAxis: 'y', elements: { bar: { borderWidth: 2, } }, plugins: { legend: { display: true, position: "bottom", align: "left", labels: { boxWidth: 12 // 调整图例方块大小 }, // 自定义图例生成器 generateLabels: function(chart) { const labels = chart.data.labels; return labels.map((label, index) => ({ text: label, fillStyle: barColors[index], strokeStyle: barColors[index], lineWidth: 1, // 控制图例点击时的状态 hidden: !chart.getDataVisibility(index), index: index })); } }, // 处理图例点击事件 onClick: function(e, legendItem) { const index = legendItem.index; const chart = this.chart; const currentVisibility = chart.getDataVisibility(index); chart.setDataVisibility(index, !currentVisibility); chart.update(); } }, scales: { y: { categorySpacing: 0, // 分类间间距 barThickness: 30, // 条形固定宽度,可根据需求调整 maxBarThickness: 50 // 可选,限制最大宽度 }, x: { beginAtZero: true, ticks: { callback: function (value) { return value.toFixed(0) + '%'; }, }, title: { // 3.x版本用title替代scaleLabel display: true, text: 'Percentage', }, } } } });
HTML代码
<div style="display:inline-block; width:400px; height:400px"> <canvas id="chartId" aria-label="chart" width="350px" height="300px"></canvas> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.1.1/chart.min.js"></script>
关键说明
- 单个数据集优势:避免多数据集导致的条形宽度无法控制问题,同时减少代码冗余
- 自定义图例:通过
generateLabels生成每个Y轴条目对应的图例,onClick事件实现点击切换对应条形的显示状态 - 条形宽度控制:
barThickness设置固定宽度,categorySpacing调整分类之间的空白,适配不同布局需求 - 版本兼容:完全适配Chart.js 3.x版本,废弃2.x的旧配置语法
内容的提问来源于stack exchange,提问作者Rishabh Kapoor
相关产品推荐
相关产品推荐

