You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 21:46:22