使用Chart.js实现分组柱状图与折线图对齐问题求助
解决分组柱状图与折线图的对齐问题
问题核心:分组柱状图中,折线图默认将数据点渲染在每个标签的中心位置,但你需要让Linear(HC)折线的点与HC柱状图的柱子中心对齐。
解决方案(推荐动态适配)
通过Chart.js的**afterLayout插件钩子**,动态获取HC柱状图每个柱子的位置,将折线对应点的坐标同步过去,这种方式能适配任意数量的分组柱子,无需硬编码偏移值。
修改后的完整代码
在你的chartOptions的plugins配置中添加afterLayout钩子:
function draw_grouped_barchart( labels_data, billable_data, non_billable_data, total_data, bench_data ) { const max_y = Math.max(...total_data) * 1.25; var barChartData = { labels: labels_data, datasets: [ { label: "HC", backgroundColor: "#64218f", borderColor: "#64218f", borderWidth: 1, data: total_data, order: 2, }, { label: "Billable", backgroundColor: "#a83b8f", borderColor: "#a83b8f", borderWidth: 1, data: billable_data, order: 2, }, { label: "Non Billable", backgroundColor: "#ed8394", borderColor: "#ed8394", borderWidth: 1, data: non_billable_data, order: 2, }, { label: "Bench", backgroundColor: "#f8c7aa", borderColor: "#f8c7aa", borderWidth: 1, data: bench_data, order: 2, }, { label: "Linear (HC)", data: total_data, fill: false, borderColor: "rgb(75, 192, 192)", tension: 0.1, type: "line", order: 1, }, ], }; var chartOptions = { responsive: true, plugins: { datalabels: { anchor: "end", align: "top", formatter: (value, context) => context.datasetIndex !== 4 ? value : "", color: "#000000", font: { weight: "bold", size: 10, }, }, legend: { onClick: () => { return ""; }, position: "bottom", labels: { color: "#000000", font: { size: 10, }, usePointStyle: true, generateLabels: (chart) => { let pointStyle = []; chart.data.datasets.forEach((dataset) => { if (dataset.type === "line") { pointStyle.push("line"); } else { pointStyle.push("rect"); } }); return chart.data.datasets.map((dataset, index) => ({ text: dataset.label, fillStyle: dataset.backgroundColor, strokeStyle: dataset.borderColor, pointStyle: pointStyle[index], })); }, }, }, title: { display: false, text: "Allocations Projections (in FTE)", }, // 新增:动态对齐折线点与HC柱子 afterLayout: (chart) => { // 获取HC柱状图的元数据(第一个数据集,索引0) const barDatasetMeta = chart.getDatasetMeta(0); // 获取折线图的元数据(第五个数据集,索引4) const lineDatasetMeta = chart.getDatasetMeta(4); // 将每个折线点的x坐标设置为对应HC柱子的x坐标 lineDatasetMeta.data.forEach((linePoint, index) => { const barPoint = barDatasetMeta.data[index]; if (barPoint) { linePoint.x = barPoint.x; } }); } }, scales: { y: { display: false, beginAtZero: true, max: max_y, }, x: { display: true, grid: { display: false, }, ticks: { color: "#000000", font: { size: 10, }, }, border: { color: "#000000", width: 2, z: 1, }, }, }, }; Chart.register(ChartDataLabels); $("#canvas").remove(); $("#mycanvas").append( '<canvas class="w-100" id="canvas" height="350"></canvas>' ); var ctx = document.getElementById("canvas").getContext("2d"); window.myBar = new Chart(ctx, { type: "bar", data: barChartData, options: chartOptions, }); }
为什么之前的offset/transform无效?
offset是针对整个X轴的全局偏移,transform是对图表整体的变换,都无法精准定位到每个分组内的单个柱子位置。而上述方法直接获取HC柱子的实际渲染坐标,能实现点对点的精准对齐。
内容的提问来源于stack exchange,提问作者SRI CHARAN PENDLI
相关产品推荐
相关产品推荐

