George Findulov
George Findulov

Reputation: 789

ChartJS bar chart - trigger hover even when the cursor is outside of the bar

I have a bar chart created using ChartJS and I've implemented a custom tooltip which is shown to hover two-week periods. The tooltip is being shown only when I hover a specific bar and that's the normal default behavior. What I need to achieve is to trigger the tooltip even when my cursor is outside of a bar (but still in the canvas of course). I want to hover over any white area (like shown on the screenshot) and still have the tooltip triggered.

I've been thinking about something like getting the closest coordinate of the nearest bar and triggering programmatically the tooltip but I haven't come up with a solution for this approach yet.

enter image description here

So far I've found this general hover event callback:

var options = {
   hover: {onHover: function (event, chartElement) {
      if (chartElement.length === 0) {
          // chartElement[0] appears to be the currently active element if I hover a bar.
          // Otherwise it's just an empty array.
      }
   }
}

Any help is highly appreciated. Thanks!

Upvotes: 2

Views: 1864

Answers (1)

LeeLenalee
LeeLenalee

Reputation: 31439

What you want can be achieved by setting the tooltip config mode and intersect like this:

options: {
  tooltips: {
    enabled: false,
    mode: 'index',
    position: 'nearest',
    intersect: false,
    custom: customTooltips
  }
} 

example:

var customTooltips = function(tooltip) {
  // Tooltip Element
  var tooltipEl = document.getElementById('chartjs-tooltip');

  if (!tooltipEl) {
    tooltipEl = document.createElement('div');
    tooltipEl.id = 'chartjs-tooltip';
    tooltipEl.innerHTML = '<table></table>';
    this._chart.canvas.parentNode.appendChild(tooltipEl);
  }

  // Hide if no tooltip
  if (tooltip.opacity === 0) {
    tooltipEl.style.opacity = 0;
    return;
  }

  // Set caret Position
  tooltipEl.classList.remove('above', 'below', 'no-transform');
  if (tooltip.yAlign) {
    tooltipEl.classList.add(tooltip.yAlign);
  } else {
    tooltipEl.classList.add('no-transform');
  }

  function getBody(bodyItem) {
    return bodyItem.lines;
  }

  // Set Text
  if (tooltip.body) {
    var titleLines = tooltip.title || [];
    var bodyLines = tooltip.body.map(getBody);

    var innerHtml = '<thead>';

    titleLines.forEach(function(title) {
      innerHtml += '<tr><th>' + title + '</th></tr>';
    });
    innerHtml += '</thead><tbody>';

    bodyLines.forEach(function(body, i) {
      var colors = tooltip.labelColors[i];
      var style = 'background:' + colors.backgroundColor;
      style += '; border-color:' + colors.borderColor;
      style += '; border-width: 2px';
      var span = '<span class="chartjs-tooltip-key" style="' + style + '"></span>';
      innerHtml += '<tr><td>' + span + body + '</td></tr>';
    });
    innerHtml += '</tbody>';

    var tableRoot = tooltipEl.querySelector('table');
    tableRoot.innerHTML = innerHtml;
  }

  var positionY = this._chart.canvas.offsetTop;
  var positionX = this._chart.canvas.offsetLeft;

  // Display, position, and set styles for font
  tooltipEl.style.opacity = 1;
  tooltipEl.style.left = positionX + tooltip.caretX + 'px';
  tooltipEl.style.top = positionY + tooltip.caretY + 'px';
  tooltipEl.style.fontFamily = tooltip._bodyFontFamily;
  tooltipEl.style.fontSize = tooltip.bodyFontSize + 'px';
  tooltipEl.style.fontStyle = tooltip._bodyFontStyle;
  tooltipEl.style.padding = tooltip.yPadding + 'px ' + tooltip.xPadding + 'px';
};


var options = {
  type: 'bar',
  data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [{
      label: '# of Votes',
      data: [12, 19, 3, 5, 2, 3],
      borderWidth: 1,
      fill: false,
      borderColor: 'red',
      backgroundColor: 'red'
    }]
  },
  options: {
    tooltips: {
      enabled: false,
      mode: 'index',
      position: 'nearest',
      intersect: false,
      custom: customTooltips
    }
  }
}



var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
canvas {
  -moz-user-select: none;
  -webkit-user-select: none;
  -ms-user-select: none;
}

#chartjs-tooltip {
  opacity: 1;
  position: absolute;
  background: rgba(0, 0, 0, .7);
  color: white;
  border-radius: 3px;
  -webkit-transition: all .1s ease;
  transition: all .1s ease;
  pointer-events: none;
  -webkit-transform: translate(-50%, 0);
  transform: translate(-50%, 0);
}

.chartjs-tooltip-key {
  display: inline-block;
  width: 10px;
  height: 10px;
  margin-right: 10px;
}
<body>
  <canvas id="chartJSContainer" width="600" height="400"></canvas>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js" integrity="sha512-hZf9Qhp3rlDJBvAKvmiG+goaaKRZA6LKUO35oK6EsM0/kjPK32Yw7URqrq3Q+Nvbbt8Usss+IekL7CRn83dYmw==" crossorigin="anonymous"></script>
</body>

Upvotes: 4

Related Questions