You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chart.js柱状图悬停时Tooltip与柱内数值重叠问题求助

解决Chart.js柱状图Tooltip与柱内数值重叠问题

我看了你配置的ChartOptions,问题出在你通过animation.onComplete手动在柱子上绘制了数值,而Chart.js默认的Tooltip组件会在悬停时靠近数据点显示,两者位置没有错开,就导致了重叠。下面给你几个可行的解决方案:


方案1:调整Tooltip的显示位置,远离柱内文字

你可以在tooltips配置里添加位置偏移或调整间距,让Tooltip主动避开柱内的数值:

public ChartOptions: any = {
  // 其他原有配置不变...
  tooltips: {
    headerFormat: '',
    custom: function (tooltip) {
      if (!tooltip) return;
      tooltip.displayColors = false;
      tooltip.titleFontSize = 0;
      // 新增:根据数值正负调整Tooltip的Y轴偏移
      if (tooltip.body && tooltip.body.length > 0) {
        const yValue = parseFloat(tooltip.body[0].lines[1].split(': ')[1]);
        tooltip.y += yValue >= 0 ? -20 : 20; // 正数值时Tooltip上移,负数值时下移
      }
    },
    mode: 'label',
    callbacks: {
      title: function () { },
      label: function (tooltipItem, data) {
        return ["Year : " + tooltipItem.xLabel, "Return : " + tooltipItem.yLabel + '%'];
      }
    },
    position: 'nearest',
    caretPadding: 10 // 增加Tooltip与数据点的基础间距
  },
  // 其他原有配置不变...
};

方案2:调整柱内绘制文字的位置,加大与Tooltip的间距

修改animation.onComplete里计算y_pos的逻辑,让文字离Tooltip的默认显示位置更远:

animation: {
  duration: 0,
  onComplete: function () {
    var ctx = this.chart.ctx;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'bottom';
    ctx.fillStyle = "#fff";
    ctx.fontStyle = "bold";
    var maxBar = 0;
    this.data.datasets.forEach(dataset => {
      maxBar += Math.max.apply(null, dataset.data.map(Math.abs));
    });
    this.data.datasets.forEach(function (dataset) {
      for (var i = 0; i < dataset.data.length; i++) {
        var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model;
        // 调整y轴偏移量,拉大与Tooltip的距离
        var y_pos = dataset.data[i] >= 0 ? model.y + 25 : model.y - 10;
        if (maxBar / Math.abs(dataset.data[i]) < 30) {
          var data = dataset.data[i];
          ctx.fillText((data == 0 || data == 0.0) ? "NA" : data + "%", model.x, y_pos);
        }
      }
    });
  }
},

方案3:Tooltip显示时隐藏柱内文字,隐藏时再显示

利用Chart.js的hover事件和自定义状态,控制柱内文字的显示时机,彻底避免重叠:

首先在组件类里定义一个状态变量:

private isTooltipActive = false;

然后修改ChartOptions,添加hover事件监听并在绘制逻辑中判断状态:

public ChartOptions: any = {
  // 其他原有配置不变...
  hover: {
    animationDuration: 0,
    onHover: function(event, chartElements) {
      // 悬停元素时标记Tooltip激活状态
      this.isTooltipActive = chartElements.length > 0;
      // 触发图表重绘
      this.chart.draw();
    }.bind(this) // 绑定组件上下文,确保能访问isTooltipActive
  },
  animation: {
    duration: 0,
    onComplete: function () {
      // Tooltip激活时不绘制柱内文字
      if (this.isTooltipActive) return;
      
      var ctx = this.chart.ctx;
      ctx.textAlign = 'center';
      ctx.textBaseline = 'bottom';
      ctx.fillStyle = "#fff";
      ctx.fontStyle = "bold";
      var maxBar = 0;
      this.data.datasets.forEach(dataset => {
        maxBar += Math.max.apply(null, dataset.data.map(Math.abs));
      });
      this.data.datasets.forEach(function (dataset) {
        for (var i = 0; i < dataset.data.length; i++) {
          var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model;
          var y_pos = model.y + 18;
          if (dataset.data[i] < 0) {
            y_pos = (model.y) - 2;
          }
          if (maxBar / Math.abs(dataset.data[i]) < 30) {
            var data = dataset.data[i];
            ctx.fillText((data == 0 || data == 0.0) ? "NA" : data + "%", model.x, y_pos);
          }
        }
      });
    }.bind(this) // 绑定组件上下文
  },
  // 其他原有配置不变...
};

这个方案会在用户悬停柱子时自动隐藏柱内数值,Tooltip消失后再恢复显示,交互体验更流畅。


你可以根据自己的需求选择方案:方案1、2调整成本低,适合快速解决;方案3交互更友好,适合追求细节体验的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:46:20