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
相关产品推荐
相关产品推荐

