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

React+TypeScript中处理OnClick事件及点击显示子图表的实现

React + TypeScript 中处理图表点击事件并展开详情图表的实现方案

一、处理图表的 onClick 事件

react-chartjs-2 的 <Bar> 组件原生支持 onClick 属性,结合 TypeScript 只需正确定义事件参数类型即可实现点击逻辑,步骤如下:

  • 导入 chart.js 提供的事件与元素类型,保证类型校验合法
  • 给 <Bar> 组件绑定点击回调函数,在回调中解析点击的图表元素,提取对应数据信息

二、点击展开详情图表

通过 React 状态管理控制详情图表的显示/隐藏,存储点击选中的数据后,根据状态条件渲染详情图表。

完整修改后的代码

import React, { useState } from 'react';
import {
  Chart as ChartJS,
  CategoryScale,
  LinearScale,
  BarElement,
  Title,
  Tooltip,
  Legend,
  ChartEvent,
  ActiveElement,
} from 'chart.js';
import { Bar } from 'react-chartjs-2';
import { faker } from '@faker-js/faker';

// 注册 Chart.js 所需组件
ChartJS.register(
  CategoryScale,
  LinearScale,
  BarElement,
  Title,
  Tooltip,
  Legend
);

// 定义图表配置选项类型
type ChartOptions = typeof options;
export const options: ChartOptions = {
  plugins: {
    title: {
      display: true,
      text: 'Chart.js Bar Chart - Stacked',
    },
  },
  responsive: true,
  scales: {
    x: {
      stacked: true,
    },
    y: {
      stacked: true,
    },
  },
};

const labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];

// 定义数据集类型
type Dataset = {
  label: string;
  data: number[];
  backgroundColor: string;
};

export const data = {
  labels,
  datasets: [
    {
      label: 'Dataset 1',
      data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
      backgroundColor: 'rgb(255, 99, 132)',
    },
    {
      label: 'Dataset 2',
      data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
      backgroundColor: 'rgb(75, 192, 192)',
    },
    {
      label: 'Dataset 3',
      data: labels.map(() => faker.datatype.number({ min: -1000, max: 1000 })),
      backgroundColor: 'rgb(53, 162, 235)',
    },
  ] as Dataset[],
};

// 定义选中数据的类型
type SelectedData = {
  label: string;
  dataset: Dataset;
  value: number;
} | null;

export function BarChart() {
  // 状态管理:存储选中的图表数据,控制详情图表显示
  const [selectedData, setSelectedData] = useState<SelectedData>(null);

  // 处理图表点击事件
  const handleChartClick = (event: ChartEvent, activeElements: ActiveElement[]) => {
    if (activeElements.length === 0) return;

    // 获取点击元素对应的数据集与标签
    const activeElement = activeElements[0];
    const datasetIndex = activeElement.datasetIndex;
    const labelIndex = activeElement.index;

    const selectedDataset = data.datasets[datasetIndex];
    const selectedLabel = data.labels[labelIndex];
    const selectedValue = selectedDataset.data[labelIndex];

    // 更新选中状态
    setSelectedData({
      label: selectedLabel,
      dataset: selectedDataset,
      value: selectedValue,
    });
  };

  // 详情图表的配置与数据
  const detailOptions: ChartOptions = {
    plugins: {
      title: {
        display: true,
        text: `详情:${selectedData?.label} - ${selectedData?.dataset.label}`,
      },
    },
    responsive: true,
    scales: {
      y: {
        beginAtZero: true,
      },
    },
  };

  const detailData = selectedData
    ? {
        labels: [selectedData.label],
        datasets: [
          {
            label: selectedData.dataset.label,
            data: [selectedData.value],
            backgroundColor: selectedData.dataset.backgroundColor,
          },
        ],
      }
    : null;

  return (
    <div style={{ width: 1500, padding: '20px' }}>
      <Bar
        options={options}
        width={80}
        height={300}
        data={data}
        onClick={handleChartClick}
      />
      {/* 条件渲染详情图表 */}
      {selectedData && detailData && (
        <div style={{ marginTop: '30px', width: 600 }}>
          <Bar options={detailOptions} data={detailData} />
        </div>
      )}
    </div>
  );
}

代码说明

  • 类型定义:通过 Dataset、SelectedData 等 TypeScript 类型约束数据结构,避免类型错误
  • 点击事件处理:handleChartClick 解析点击的图表元素,提取标签、数据集和数值后更新状态
  • 状态控制:selectedData 状态决定详情图表的显示状态,无选中项时自动隐藏
  • 条件渲染:根据选中状态渲染详情图表,同时传递对应的数据和配置

内容的提问来源于stack exchange,提问作者Ellis b

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 10:52:04