突出显示 “selected” 部分的图表.js 饼图,在点击时将其视为悬停状态。

huangapple go评论58阅读模式
英文:

highlight a "selected" slice of chart.js pie as being hovered when clicked

问题

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.

英文:

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.

答案1

得分: 0

以下是您提供的内容的中文翻译部分:

  1. 在评论中分享,这里是一个用例的可能解决方案,作为起点。
    简短描述:

    1. 在图表级别添加了 onClick 选项,以选择数据元素。
    2. 添加了自定义交互,以添加悬停的元素(按点模式)和选定的项目(如果有的话)。
    3. 添加了自定义插件,以保持选定的项目,即使鼠标移出图表区域和画布。

    如所述,这是一个起点,可以根据需要添加自己的逻辑(例如,如何取消选择项目)。

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>

编辑:显示工具提示。

英文:

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

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

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 =&gt; e.index !== selected.index));
} else {
activeElements.push(...pointItems);
}
}
return activeElements;
};
const foods = [
{ value: 60, label: &#39;Orange&#39; },
{ value: 40, label: &#39;Banana&#39; },
{ value: 20, label: &#39;Strawberry&#39; },
];
const data = {
labels: foods.map(food =&gt; food.label),
datasets: [
{
label: &#39;Foods&#39;,
data: foods.map(food =&gt; food.value),
backgroundColor: [
&#39;rgba(255, 99, 132, 0.2)&#39;,
&#39;rgba(54, 162, 235, 0.2)&#39;,
&#39;rgba(255, 206, 86, 0.2)&#39;,
],
hoverBackgroundColor: [
&#39;rgba(255, 99, 132, 1)&#39;,
&#39;rgba(54, 162, 235, 1)&#39;,
&#39;rgba(255, 206, 86, 1)&#39;,
],
borderWidth: 0,
hoverOffset: 4
},
],
};
const options = {
responsive: true,
interaction: {
mode: &#39;pointSelected&#39;,
intersect: true
},
onClick(event, el, chart) {
const elements = chart.getElementsAtEventForMode(event, &#39;point&#39;, {intersect: true}, true);
if (elements.length) {
selected = elements[0];
}
},
plugins: {
tooltip: {
callbacks: {
title(items) {
return items.map(e =&gt; e.label).join(&#39; and &#39;);
},
label(item) {
return item.label +&#39;: &#39;+item.formattedValue;
}
}
}
}
};
const plugin = {
id: &#39;hl&#39;,
afterEvent(chart, args) {
const event = args.event;
if (event.type === &#39;mouseout&#39; &amp;&amp; selected) {
chart.setActiveElements([selected]);
chart.tooltip.setActiveElements([selected]);
chart.update();
}
}
}
const ctx = document.getElementById(&#39;myChart&#39;).getContext(&#39;2d&#39;);
new Chart(ctx, {
type: &#39;pie&#39;,
plugins: [plugin],
data,
options
});

<!-- language: lang-css -->

.myChartDiv {
max-width: 600px;
max-height: 400px;
}

<!-- language: lang-html -->

&lt;script src=&quot;https://npmcdn.com/chart.js@latest/dist/chart.umd.js&quot;&gt;&lt;/script&gt;
&lt;div class=&quot;myChartDiv&quot;&gt;
&lt;canvas id=&quot;myChart&quot; width=&quot;600&quot; height=&quot;400&quot;&gt;&lt;/canvas&gt;
&lt;/div&gt;

<!-- end snippet -->

EDIT: show tooltip

huangapple
  • 本文由 发表于 2023年4月17日 17:28:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/76033628.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定