0

I'm working on a project with a chart.js pie. The final idea is to make the pie keep the hover animation to show that this part is activated for a search on a table until the search is reset via a button.

The pie normally shows the animation when hover and hide when mouse leave. I would like to know how to make the hover animation stay on if mouse click on when hovering over a part of the pie. I'm trying to highlight a "selected" slice as being hovered.

I manage to get the information about the click, but for the animation, I don't manage to make the “hovering” animation stay on.

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 ctx = document.getElementById('myChart').getContext('2d');
new Chart(ctx, {
  type: 'pie',
  data
});
    .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>

If anybody already made the hover display stay on, I would love to know how.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Lou
  • 11
  • 3
  • AFAIK the click on the hovered element doesn't change the state of the element, which remains hovered if the mouse is still on the pie. Can you create a reproducible example where clicking the pie the element is not hovered anymore? The use case is not clear, at least to me. – user2057925 Apr 17 '23 at 11:34
  • Yes, it was a bad choice. I update the code to be as simple as possible. I try to make the hover animation stay on the pie when I hover and click on a slice of the pie. I already manage to get the information of which slice the mouse is over and get an onclick action but keeping the hover animation, I don't find info to do it – Lou Apr 17 '23 at 11:56
  • I would need just a way to activate and deactivate the activation and deactivation of hovering animation. The final idea is to make the pie keep the hover animation to show that this part is activated for a search on a table until the search is reset via a button – Lou Apr 17 '23 at 11:58
  • Ok, therefore if I have understood correctly, when you click on the chart, the slice of the pie must be maintain the "hover" options even if the mouse is out of the element. You are trying to highlight a "selected" slice as being hovered – user2057925 Apr 17 '23 at 12:02
  • Yesss ! It's exactly that ! ;) I also updated my question. – Lou Apr 17 '23 at 12:06
  • It's a bit complex. Let me take time to propose you something consistent. The hover is managed internally and there isn't any concept about selected item. There are couple of options (i.e. change the colors/options of selected item). Animation does not affect the hovering. – user2057925 Apr 17 '23 at 12:20
  • Have a look to the codepen: https://codepen.io/stockinail/pen/dygXNrO It's maintaining the selection if the mouse is remaining on chart area. – user2057925 Apr 17 '23 at 12:55
  • Updated in order to maintain the selected item even if the mouse is going out of canvas, by a custom plugin, setting active element. – user2057925 Apr 17 '23 at 13:11
  • If it's what you want, I can add the answer for all others. Let me know – user2057925 Apr 17 '23 at 13:15
  • Please provide enough code so others can better understand or reproduce the problem. – Community Apr 17 '23 at 13:27
  • It's already better than what I had, but I would like to keep the “overlay” that give the information of the selected part display if it's possible ? – Lou Apr 17 '23 at 13:35
  • I really like what you made, thank you a lot already ! – Lou Apr 17 '23 at 13:39

1 Answers1

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

user2057925
  • 2,377
  • 1
  • 12
  • 12
  • Do you think we can also force the label to stay displayed ? – Lou Apr 17 '23 at 14:53
  • When you say "label", what do you mean exactly? tooltip? legend? or? – user2057925 Apr 17 '23 at 14:58
  • I don't really know, for exemple in your answer it would be : "Orange Foods : 60" or "Banana Foods : 40" ... Because in your answer, it stays display only if we hover on the chart. I would need it to stay display even if the mouse is somewhere else. – Lou Apr 17 '23 at 15:04
  • Ok, you are talking about tooltip. And this is more complex... wait for an update to the answer – user2057925 Apr 17 '23 at 15:11
  • I might find the answer here : https://stackoverflow.com/questions/36992922/chart-js-v2-how-to-make-tooltips-always-appear-on-pie-chart – Lou Apr 17 '23 at 15:20
  • Done. Have a look now if it looks like as you need. Updated the answer – user2057925 Apr 17 '23 at 15:28
  • It's exactly what I was aiming for ! I will make the changes in my project, thank you a lot ! – Lou Apr 17 '23 at 15:32