如何在react-chartjs-2中扩展Doughnut图例的onClick事件?
React-Chartjs-2 Doughnut 图图例 onClick 事件扩展实现
问题描述
我需要扩展react-chartjs-2中Doughnut图表图例的onClick事件实现。根据Chart.js文档,图例onClick默认功能如下:
function(e, legendItem, legend) { const index = legendItem.datasetIndex; const ci = legend.chart; if (ci.isDatasetVisible(index)) { ci.hide(index); legendItem.hidden = true; } else { ci.show(index); legendItem.hidden = false; } }
但将这段代码复制到项目中完全无效,尝试加入toggleDataVisibility也没用,还发现legendItem不存在datasetIndex属性。我希望保留onClick的默认功能并添加自定义功能,请问该如何实现?以下是我的代码:
<Doughnut ref={chartRef} options={{ responsive: true, maintainAspectRatio: false, layout: { padding: { bottom(ctx) { return resizeChart(ctx); }, left(ctx) { return resizeChart(ctx); }, right(ctx) { return resizeChart(ctx); }, }, }, plugins: { tooltip: { xAlign: 'center', }, legend: { position: 'top', labels: { color: cssvar('--textfield-standard'), }, onClick: function (e, legendItem, legend) { const { index } = legendItem; const ci = legend.chart; console.log(legendItem); ci.toggleDataVisibility(index ); if (ci.getDataVisibility(index )) { ci.hide(index ); legendItem.hidden = false; } else { ci.show(index ); legendItem.hidden = true; } }, }, }, }} data={{ labels: [ `${translate(language, 'Free')}, ${hddData?.statistic?.unit_size}`, `${translate(language, 'Used')}, ${hddData?.statistic?.unit_size}`, `${translate(language, 'Logs')}, ${hddData?.statistic?.unit_size}`, ], datasets: [ { data: [hddData?.statistic?.free, hddData?.statistic?.used, hddData?.log_used], backgroundColor: [ cssvar('--dashboard-doughuny-free'), cssvar('--dashboard-doughuny-used'), 'red', ], borderColor: ['rgba(67, 137, 137, 1)', 'rgba(249, 168, 37, 1)', 'green'], borderWidth: 1, hoverOffset: 15, hoverBackgroundColor: [ cssvar('--dashboard-doughuny-used-hover'), 'orange', cssvar('--dashboard-doughuny-free-hover'), ], }, ], }} />
解决方案
问题根源
你遇到的问题是因为Chart.js 3.x+ 中,单数据集的图表(比如你的Doughnut图),图例项对应的是数据项而非数据集。文档里的默认逻辑是针对多数据集场景的,所以legendItem里没有datasetIndex,取而代之的是index(对应单数据集中的第几个数据项)。
正确实现方式
要保留默认切换显示/隐藏的功能并添加自定义逻辑,有两种可行方式:
方式1:调用默认的图例onClick方法
先获取Chart.js默认的图例onClick函数,执行它之后再添加你的自定义代码:
import { Chart } from 'chart.js'; // ... <Doughnut ref={chartRef} options={{ // 其他配置保持不变 plugins: { legend: { // 其他图例配置保持不变 onClick: function(e, legendItem, legend) { // 调用Chart.js默认的图例onClick逻辑 Chart.defaults.plugins.legend.onClick.call(this, e, legendItem, legend); // 这里添加你的自定义功能 console.log("自定义逻辑触发,当前点击的图例项索引:", legendItem.index); // 示例:更新组件状态、发送统计请求等操作 } } } }} // ...其他props保持不变 />
方式2:手动实现默认逻辑+自定义功能
如果需要更精细的控制,可以手动实现切换逻辑,再追加自定义代码:
<Doughnut ref={chartRef} options={{ // 其他配置保持不变 plugins: { legend: { // 其他图例配置保持不变 onClick: function(e, legendItem, legend) { const ci = legend.chart; const dataIndex = legendItem.index; // 执行默认切换逻辑:切换数据项可见性 ci.toggleDataVisibility(dataIndex); // 更新图例项的隐藏状态 legendItem.hidden = !ci.getDataVisibility(dataIndex); // 触发图表重绘,让变更生效 ci.update(); // 这里添加你的自定义功能 console.log("数据项", dataIndex, "的可见状态变为:", ci.getDataVisibility(dataIndex)); // 示例:更新组件内部状态 // setVisibleItems(prev => ({ ...prev, [dataIndex]: ci.getDataVisibility(dataIndex) })); } } } }} // ...其他props保持不变 />
关键注意点
- 单数据集图表的图例项用
legendItem.index,多数据集场景才用legendItem.datasetIndex - 执行完切换逻辑后,方式2需要手动调用
ci.update()触发图表重绘;方式1中默认方法已包含重绘逻辑,无需手动调用 - 不要混用
hide()/show()和toggleDataVisibility():前者针对数据集,后者针对数据项,你的场景用toggleDataVisibility()更匹配
内容的提问来源于stack exchange,提问作者Andrej Amelyanovich
相关产品推荐
相关产品推荐

