Chartjs-Highlight a "selected" slice of chart.js pie as being hovered when clicked

0👍

As shared in comments, here a possible solution for the use case, as starting point.
Short description:

  1. added onClick option at chart level in order to select the data element
  2. added a custom interaction in order to add the hovered elements (by point mode) and the selected item (if there is)
  3. add a custom plugin to maintain the selected item even if the mouse is out of the chart area and canvas.

As written, it’s a starting point that it can be customized adding own logic (i.e. how to de-select the item).

let selected;
Chart.Interaction.modes.pointSelected = function(chart, e, options, useFinalPosition) {
   const activeElements = [];
   if (selected) {
     activeElements.push(selected);
   }
  const pointItems = Chart.Interaction.modes.point(chart, e, {intersect: true}, useFinalPosition);
  if (pointItems.length) {
    if (selected) {
      activeElements.push(...pointItems.filter(e => e.index !== selected.index));
    } else {
      activeElements.push(...pointItems);
    }
  }
  return activeElements;
};

const foods = [
    { value: 60, label: 'Orange' },
    { value: 40, label: 'Banana' },
    { value: 20, label: 'Strawberry' },
  ];
const data = {
        labels: foods.map(food => food.label),
        datasets: [
          {
            label: 'Foods',
            data: foods.map(food => food.value),
            backgroundColor: [
                'rgba(255, 99, 132, 0.2)',
                'rgba(54, 162, 235, 0.2)',
                'rgba(255, 206, 86, 0.2)',
            ],
            hoverBackgroundColor: [
                'rgba(255, 99, 132, 1)',
                'rgba(54, 162, 235, 1)',
                'rgba(255, 206, 86, 1)',
            ],
            borderWidth: 0,
            hoverOffset: 4
          },
        ],
    };
const options = {
   responsive: true,
   interaction: {
     mode: 'pointSelected',
     intersect: true
   },
   onClick(event, el, chart) {
     const elements = chart.getElementsAtEventForMode(event, 'point', {intersect: true}, true);
     if (elements.length) {
       selected = elements[0];
     }
   },
  plugins: {
    tooltip: {
      callbacks: {
        title(items) {
          return items.map(e => e.label).join(' and ');
        },
        label(item) {
          return item.label +': '+item.formattedValue;
        }
      }
    }
  }
};

const plugin = {
  id: 'hl',
  afterEvent(chart, args) {
    const event = args.event;
    if (event.type === 'mouseout' && selected) {
      chart.setActiveElements([selected]);
      chart.tooltip.setActiveElements([selected]);
      chart.update();
    }
  }
}
const ctx = document.getElementById('myChart').getContext('2d');
new Chart(ctx, {
  type: 'pie',
  plugins: [plugin],
  data,
  options
});
.myChartDiv {
  max-width: 600px;
  max-height: 400px;
}
<script src="https://npmcdn.com/chart.js@latest/dist/chart.umd.js"></script>
<div class="myChartDiv">
  <canvas id="myChart" width="600" height="400"></canvas>
</div>

EDIT: show tooltip

Leave a comment