You need to enable JavaScript to run this app. Chart.js 2.9.4 可点击标签跳转报Cannot read property 'top'错误
优惠活动
大模型
产品
解决方案
定价
更多

Chart.js 2.9.4 可点击标签跳转报Cannot read property 'top'错误

报错原因定位
  • 直接触发报错的问题:jQuery选择器和实际DOM不匹配。你初始化图表的canvas元素实际id为barChart-mostSold,但在onClick回调中使用$('#chartmostSold')选择元素,无法匹配到对应DOM,调用.offset()会返回undefined,读取undefined的top属性就会抛出Cannot read property 'top' of undefined的错误。
  • 原有逻辑的适配缺陷:你使用的是horizontalBar横向条形图,类别标签默认渲染在左侧y轴,而原参考方案针对的是垂直柱状图的底部x轴标签场景,就算解决了选择器问题,原有坐标判断逻辑也完全错位,无法正确命中标签区域。
适配Chart.js 2.9.4的可点击标签实现方案

实现思路:放弃手动计算DOM偏移、刻度宽度的脆弱逻辑,直接调用2.9.4版本内置的坐标轴API完成标签命中判断,适配横向条形图的轴结构。

var ctx = document.getElementById("barChart-mostSold").getContext('2d');
// 提前维护标签与跳转路径的映射,顺序与labels数组一一对应即可
const labelRedirectMap = [
  '/page-a', // 对应labels[0]的跳转地址
  '/page-b', // 对应labels[1]的跳转地址
  // 按实际标签顺序补全剩余路径
];
this.chartmostSold = new Chart(ctx, {
  type: 'horizontalBar',
  data: {
    labels: {{listTopIssuerSoldLabel | tojson }},
    datasets: [
      {
        data: {{listTopIssuerSoldValue | tojson }}
      }
    ]
  },
  options: {
    events: ["mousemove", "mouseout", "click", "touchstart", "touchmove", "touchend"],
    onClick: function(e) {
      // 先判断点击是否命中条形块,命中则不触发标签跳转逻辑
      const activeBars = this.getElementAtEvent(e);
      if (activeBars.length === 0) {
        const yScale = this.scales['y-axis-0'];
        const tickCount = yScale.ticks.length;
        // 遍历所有y轴刻度,判断点击坐标是否落在标签渲染范围内
        for (let i = 0; i < tickCount; i++) {
          const tickCenterY = yScale.getPixelForTick(i);
          // 计算当前标签的上下覆盖区间,取相邻刻度间距的一半作为边界
          const nextTickCenterY = i < tickCount -1 ? yScale.getPixelForTick(i+1) : yScale.bottom;
          const tickRange = Math.abs(nextTickCenterY - tickCenterY);
          if (e.offsetY > (tickCenterY - tickRange/2) && e.offsetY < (tickCenterY + tickRange/2)) {
            window.location.href = labelRedirectMap[i];
            break;
          }
        }
      }
    },
    // 可选:鼠标悬停在标签上时切换为手型,提升交互感知
    onHover: function(e) {
      const activeBars = this.getElementAtEvent(e);
      if (activeBars.length === 0) {
        const yScale = this.scales['y-axis-0'];
        const tickCount = yScale.ticks.length;
        for (let i = 0; i < tickCount; i++) {
          const tickCenterY = yScale.getPixelForTick(i);
          const nextTickCenterY = i < tickCount -1 ? yScale.getPixelForTick(i+1) : yScale.bottom;
          const tickRange = Math.abs(nextTickCenterY - tickCenterY);
          if (e.offsetY > (tickCenterY - tickRange/2) && e.offsetY < (tickCenterY + tickRange/2)) {
            e.target.style.cursor = 'pointer';
            return;
          }
        }
      }
      e.target.style.cursor = 'default';
    }
  }
});
方案核心说明
  • 不需要依赖jQuery计算页面滚动偏移,所有坐标判断都基于canvas自身的坐标系完成,减少跨环境兼容问题。
  • 针对横向条形图的y轴标签做命中判断,和垂直柱图的x轴标签逻辑做了适配,不会出现轴错位问题。
  • 跳转路径和图表标签解耦维护,不需要修改原有图表数据结构,调整跳转逻辑时只需要维护labelRedirectMap数组即可。
  • 完全适配2.9.4版本的API能力,不需要升级Chart.js版本或者引入第三方插件。

内容的提问来源于stack exchange,提问作者Damiano Dotto

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.08 16:24:00