Chart.js - 条形图上的水平线干扰工具提示

Chart.js - Horizontal line on Bar chart interferes with tooltip

我正在使用 Chart.js 2.6 并且我已经实现了 horizo​​ntalLine 插件来在我的条形图上显示平均值。它工作正常,但是当工具提示显示在它与线相交的位置时,它会被水平线本身部分覆盖。我想弄清楚如何使工具提示在水平线上方绘制。

我知道工具提示是 canvas 元素的一部分,因此没有 z-index 属性。我怎样才能做到这一点?

这是我用于水平线插件的内容。

var horizonalLinePlugin = {
    afterDraw: function(chartInstance) {
        var yScale = chartInstance.scales["y-axis-0"];
        var canvas = chartInstance.chart;
        var ctx = canvas.ctx;
        var index, line, style, width;
        if (chartInstance.options.horizontalLine) {
            for (index = 0; index < chartInstance.options.horizontalLine.length; index++) {
                line = chartInstance.options.horizontalLine[index];
                style = (line.style) ? line.style : "rgba(169,169,169, .6)";
                yValue = (line.y) ? yScale.getPixelForValue(line.y) : 0 ;
                ctx.lineWidth = (line.width) ? line.width : 3;              
                if (yValue) {
                    ctx.beginPath();
                    ctx.moveTo(chartInstance.chartArea.left, yValue);
                    ctx.lineTo(canvas.width, yValue);
                    ctx.strokeStyle = style;
                    ctx.stroke();
                }
                if (line.text) {
                    ctx.fillStyle = style;
                    ctx.fillText(line.text, 0, yValue + ctx.lineWidth);
                }
            }
            return;
        }
    }
};

Chart.pluginService.register(horizonalLinePlugin);

...然后我使用以下方法将其添加到条形图选项中

options: {
     ...standard option stuff...
     "horizontalLine": [{
          "y": averageValue,
          "style" : colorOfTheLine
     }]
}

生成如下图所示的图表。

..然而,当您将鼠标悬停在图表的某个片段上以显示工具提示时,并且工具提示位于水平线的路径中时,会导致如下所示的问题。

将您的插件附加到 afterDatasetDraw 挂钩,而不是 afterDraw 。这将使水平线绘制在工具提示之前。

var horizonalLinePlugin = {
   afterDatasetDraw: function(chartInstance) {
      var yScale = chartInstance.scales["y-axis-0"];
      var canvas = chartInstance.chart;
      var ctx = canvas.ctx;
      var index, line, style, width;
      if (chartInstance.options.horizontalLine) {
         for (index = 0; index < chartInstance.options.horizontalLine.length; index++) {
            line = chartInstance.options.horizontalLine[index];
            style = (line.style) ? line.style : "rgba(169,169,169, .6)";
            yValue = (line.y) ? yScale.getPixelForValue(line.y) : 0;
            ctx.lineWidth = (line.width) ? line.width : 3;
            if (yValue) {
               ctx.beginPath();
               ctx.moveTo(chartInstance.chartArea.left, yValue);
               ctx.lineTo(canvas.width, yValue);
               ctx.strokeStyle = style;
               ctx.stroke();
            }
            if (line.text) {
               ctx.fillStyle = style;
               ctx.fillText(line.text, 0, yValue + ctx.lineWidth);
            }
         }
         return;
      }
   }
};

Chart.pluginService.register(horizonalLinePlugin);

new Chart(canvas, {
   type: 'bar',
   data: {
      labels: ["January", "February"],
      datasets: [{
         label: "Dataset 1",
         data: [80, 50]
      }]
   },
   options: {
      scales: {
         yAxes: [{
            ticks: {
               beginAtZero: true
            }
         }]
      },
      horizontalLine: [{
         y: 50,
         style: 'red'
      }]
   }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<canvas id="canvas"></canvas>