kennysong
kennysong

Reputation: 2134

How to change tooltip direction in Chart.js (2.9.4)?

I have a stacked bar chart in Chart.js 2.9.4.

On hovering, the tooltip's tip is positioned at the top-center of each bar, but the tooltip itself is rendered to the right and blocks the view of other bars.

enter image description here

I'd like to draw the tooltip above the bar. Is there a way to do this?

See the JSFiddle here.


(Here's the raw code as required by StackOverflow)

// Get the past 14 days for the x-axis
var allDates = [
    moment('2021-04-04T00:00:00'),
    moment('2021-04-05T00:00:00'),
    moment('2021-04-06T00:00:00'),
    moment('2021-04-07T00:00:00'),
    moment('2021-04-08T00:00:00'),
    moment('2021-04-09T00:00:00'),
    moment('2021-04-10T00:00:00'),
    moment('2021-04-11T00:00:00'),
    moment('2021-04-12T00:00:00'),
    moment('2021-04-13T00:00:00'),
    moment('2021-04-14T00:00:00'),
    moment('2021-04-15T00:00:00'),
    moment('2021-04-16T00:00:00'),
    moment('2021-04-17T00:00:00'),
    moment('2021-04-18T00:00:00'),
];

// Simulated distribution per day
var distributionPerDay = [
  [0.13, 0.05, 0.12, 0.07, 0.11, 0.14, 0.22, 0.06, 0.  , 0.1 ],
  [0.1 , 0.08, 0.1 , 0.09, 0.13, 0.12, 0.18, 0.11, 0.03, 0.06],
  [0.08, 0.1 , 0.1 , 0.09, 0.15, 0.1 , 0.2 , 0.09, 0.03, 0.06],
  [0.09, 0.09, 0.12, 0.07, 0.13, 0.12, 0.15, 0.14, 0.01, 0.08],
  [0.05, 0.05, 0.16, 0.13, 0.1 , 0.1 , 0.1 , 0.1 , 0.11, 0.1 ],
  [0.05, 0.05, 0.16, 0.13, 0.1 , 0.13, 0.1 , 0.12, 0.07, 0.09],
  [0.08, 0.05, 0.15, 0.1 , 0.13, 0.1 , 0.12, 0.13, 0.08, 0.06],
  [0.1 , 0.08, 0.13, 0.07, 0.1 , 0.13, 0.15, 0.1 , 0.05, 0.09],
  [0.08, 0.1 , 0.12, 0.08, 0.13, 0.1 , 0.13, 0.07, 0.07, 0.12],
  [0.12, 0.08, 0.1 , 0.04, 0.1 , 0.14, 0.11, 0.12, 0.09, 0.1 ],
  [0.08, 0.06, 0.16, 0.07, 0.07, 0.19, 0.07, 0.14, 0.11, 0.05],
  [0.08, 0.1 , 0.1 , 0.09, 0.1 , 0.16, 0.12, 0.12, 0.06, 0.07],
  [0.12, 0.09, 0.14, 0.04, 0.16, 0.08, 0.12, 0.1 , 0.12, 0.03],
  [0.09, 0.16, 0.1 , 0.07, 0.13, 0.1 , 0.1 , 0.11, 0.08, 0.06],
  [0.13, 0.12, 0.13, 0.04, 0.15, 0.11, 0.06, 0.12, 0.06, 0.08]
]

// Define colors for each bar (10 bars)
var colors = ['#9e0142', '#d53e4f', '#f46d43', '#fdae61', '#fee08b', '#e6f598', '#abdda4', '#66c2a5', '#3288bd', '#5e4fa2'];  // cb-Spectral

// Convert distribution into Chart.js datasets
var classNames = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
var datasets = [];
classNames.forEach(function(className, i) {
  // Gather the data {x: date, y: percentage} for this class
  var data = [];
  distributionPerDay.forEach(function(dist, j) {
    data.push({x: allDates[j], y: dist[i]});
  });

  // Add data and config to the datasets array
  datasets.push({
    label: className,
    data: data,
    backgroundColor: colors[i],
    borderWidth: 0,
    borderColor: 'black',
    hoverBorderWidth: 1,  // Show a 1px black border on hover
    borderSkipped: false,  // Draw all four borders around the bar
    minBarLength: 1  // So even a bar for 0 has 1px height
  });
});

var myChart = new Chart('my-chart', {
  type: 'bar',
  data: { datasets: datasets },
  options: {
    hover: {
      mode: 'dataset',  // Highlight an entire row on hover
      animationDuration: 0  // Otherwise there is flickering when sliding over the bars quickly
    },
    tooltips: {
      mode: 'nearest',  // Only show tooltip data of one bar on hover
    },
    scales: {
      xAxes: [{
        stacked: true,
        type: 'time',
        time: {
          unit: 'day',
        },
        offset: true,  // Otherwise the left and right bars are cut off
        ticks: { source: 'data' }  // Use one tick per point in allDates
      }],
      yAxes: [{
        stacked: true,
        ticks: {
          min: 0,
          max: 1.0
        }
      }]
    }
  }
});

Upvotes: 1

Views: 1069

Answers (1)

mcernak
mcernak

Reputation: 9130

You can set yAlign: 'bottom' in tooltip options, see the JSFiddle here

enter image description here


Relevant part of the code:

var myChart = new Chart('my-chart', {
  type: 'bar',
  data: { datasets: datasets },
  options: {
    hover: {
      mode: 'dataset',  
      animationDuration: 0
    },
    tooltips: {
      mode: 'nearest',
      yAlign: 'bottom' //use this to control the placement of the tooltip relative to its point
    },
    scales: {
      xAxes: [{
        stacked: true,
        type: 'time',
        time: {
          unit: 'day',
        },
        offset: true,
        ticks: { source: 'data' }
      }],
      yAxes: [{
        stacked: true,
        ticks: {
          min: 0,
          max: 1.0
        }
      }]
    }
  }
});

It isn't mentioned in the official documentation, but works for Chart.js 2.9.4
(you can have a look at the source code where that option is used to override the automatic alignment calculation based on tooltip and chart size)

Upvotes: 1

Related Questions