Search code examples
javascriptjquerychart.jschart.js2

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


I'm using Chart.js 2.6 and I have implemented the horizontalLine plugin to show an average value on my bar charts. It works fine, however when the tooltip displays in the spot where it intersects with the line, it is partially covered by the horizontal line itself. I'm trying to figure out how to make the tooltip draw ABOVE the horizontal line.

I understand the tooltip is part of the canvas element, and therefore does not have a z-index property. How can I accomplish this?

Here is what I'm using for my horizontal line plugin.

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);

... and then I add it to the bar chart options using the following

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

Which generates a chart that looks like the one below.

enter image description here

..however when you hover on a segment of the chart to display the tooltip, and the tooltip is in the path of the horizontal line, it causes the issue seen below.

enter image description here


Solution

  • Attach your plugin to the afterDatasetDraw hook, instead of afterDraw . This will make the horizontal line to be drawn before the tooltip.

    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>