You need to enable JavaScript to run this app. JavaScript Canvas实现的Chart.js柱状图长标签重叠,如何优化可读性?
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript Canvas实现的Chart.js柱状图长标签重叠,如何优化可读性?

Chart.js 长标签堆叠柱状图适配实现

原有代码失效的核心原因

  • 悬停模式配置错误:将原本合理的mode: 'index'改为mode: 'label',同时在tooltip回调中添加了无意义的欧元符号后缀,破坏了原有的交互逻辑,且回调中读取的xLabel是经过截断的短文本,无法展示完整标签
  • 刻度回调存在类型隐患:直接对传入的刻度值读取length属性,当值为数字等非字符串类型时,会因属性值为undefined出现截断判断失效的问题
  • 未预留画布展示空间:标签截断后没有为x轴预留足够的边距,容易出现标签被裁切的问题
  • 硬关自动跳过逻辑:将autoSkip强制设为false,即使标签做了截断,当标签数量较多时依然会出现紧密挤压的问题

可直接生效的完整实现代码

function renderBarChart(nameArray, passArray, failArray, divId, title) {
    const ctx = document.getElementById(divId).getContext('2d');
    // 预先存储原始标签映射,避免后续取值被截断逻辑干扰
    const originalLabels = [...nameArray];

    const newChart = new Chart(ctx, {
        type: 'bar',
        data: {
            labels: originalLabels,
            datasets: [
                {
                    label: 'Passed',
                    data: passArray,
                    backgroundColor: 'rgb(150,238,144)'
                },
                {
                    label: 'Failed',
                    data: failArray,
                    backgroundColor: 'rgb(204,0,0)'
                }
            ]
        },
        options: {
            title: {
                display: true,
                text: title
            },
            // 修正后的tooltip配置
            tooltips: {
                enabled: true,
                mode: 'index',
                intersect: false,
                callbacks: {
                    title: function(tooltipItems) {
                        // 根据当前悬停的刻度索引取原始完整标签
                        const currentIndex = tooltipItems[0].index;
                        return originalLabels[currentIndex];
                    },
                    label: function(tooltipItem, data) {
                        const datasetName = data.datasets[tooltipItem.datasetIndex].label;
                        return `${datasetName}: ${tooltipItem.yLabel}`;
                    }
                }
            },
            hover: {
                mode: 'nearest',
                intersect: true
            },
            responsive: false,
            maintainAspectRatio: false,
            // 预留底部展示空间,避免标签被裁切
            layout: {
                padding: { bottom: 30 }
            },
            scales: {
                xAxes: [{
                    stacked: true,
                    ticks: {
                        stepSize: 1,
                        min: 0,
                        // 开启自动防重叠跳过,搭配展示阈值减少挤压
                        autoSkip: true,
                        maxTicksLimit: 10,
                        // 允许标签最大45度倾斜,避免单行挤压重叠
                        maxRotation: 45,
                        minRotation: 0,
                        padding: 8,
                        // 修正后的截断回调,增加类型转换避免判断失效
                        callback: function(tickValue) {
                            const labelText = String(tickValue);
                            return labelText.length > 4 ? `${labelText.slice(0,4)}...` : labelText;
                        }
                    }
                }],
                yAxes: [{
                    stacked: true,
                    ticks: {
                        maxTicksLimit: 5,
                        min: 0
                    }
                }]
            }
        }
    });
}

关键配置说明

  • 标签截断逻辑:所有刻度值先转为字符串再做长度判断,超过4个字符的内容截取前4位追加省略号,从根源上避免短标签无意义截断、长标签展示过宽的问题
  • 悬停展示逻辑:保留index模式的悬停规则,当鼠标放到柱子上时,直接读取预先存储的原始标签内容作为tooltip标题,不会展示截断后的短文本
  • 防重叠优化:开启autoSkip自动跳过逻辑,搭配maxTicksLimit限制单屏最多展示10个标签,当标签数量过多时自动均匀稀疏展示;同时允许标签最多倾斜45度,即便截断后的标签宽度仍超出可用空间,也会以倾斜形式避免横向挤压重叠
  • 边距预留:通过layout.padding给图表底部预留30px的展示空间,避免倾斜后的标签被画布边缘裁切

额外可选优化:如果不需要倾斜展示标签,可以将maxRotation和minRotation都设为0,此时完全依靠截断和自动跳过逻辑保证标签单行展示不重叠

内容的提问来源于stack exchange,提问作者Mads Sander Høgstrup

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.28 06:54:03