如何在Chart.js及react-chartjs-2堆叠条形图中高亮所有条形的同一堆叠区段
解决方案
实现思路
不需要依赖额外插件,直接利用Chart.js内置的事件回调和动态样式配置即可实现需求:
- 监听图表的
onHover事件,获取当前悬停的条形段所属的数据集索引 - 为目标数据集设置高亮样式(提升不透明度、添加边框、偏移放大),同步降低非目标数据集的不透明度做弱化处理
- 触发图表重绘,鼠标移出后重置所有样式即可
react-chartjs-2 实现代码
import { useState } from 'react'; import { Bar } from 'react-chartjs-2'; import { Chart as ChartJS, CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend } from 'chart.js'; ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend); const StackedBarChart = () => { // 存储当前高亮的数据集索引,-1代表无高亮状态 const [activeDatasetIndex, setActiveDatasetIndex] = useState(-1); const options = { responsive: true, scales: { x: { stacked: true }, y: { stacked: true } }, interaction: { mode: 'nearest', intersect: true }, // 监听悬停事件 onHover: (event, elements) => { if (elements.length > 0) { const currentIndex = elements[0].datasetIndex; currentIndex !== activeDatasetIndex && setActiveDatasetIndex(currentIndex); } else { activeDatasetIndex !== -1 && setActiveDatasetIndex(-1); } } }; // 基础数据集,可根据业务自行调整 const baseDatasets = [ { label: '类别A', data: [12, 19, 13, 15], backgroundColor: 'rgba(255, 99, 132, 0.7)' }, { label: '类别B(橙色)', data: [8, 12, 6, 9], backgroundColor: 'rgba(255, 159, 64, 0.7)' }, { label: '类别C', data: [5, 7, 4, 6], backgroundColor: 'rgba(54, 162, 235, 0.7)' } ]; // 动态生成带高亮样式的数据集 const datasets = baseDatasets.map((item, index) => { const isActive = index === activeDatasetIndex; return { ...item, // 调整透明度 backgroundColor: isActive ? item.backgroundColor.replace('0.7', '1') : item.backgroundColor.replace('0.7', activeDatasetIndex === -1 ? '0.7' : '0.3'), // 高亮边框 borderColor: isActive ? '#222' : 'transparent', borderWidth: isActive ? 2 : 0, borderSkipped: false, // 偏移实现轻微放大效果 offset: isActive ? 2 : 0 } }); const chartData = { labels: ['6月1日', '6月2日', '6月3日', '6月4日'], datasets }; return <Bar options={options} data={chartData} /> }; export default StackedBarChart;
原生JS 实现逻辑
和React版本逻辑完全一致,直接操作Chart实例更新样式即可:
const ctx = document.getElementById('stackedBar').getContext('2d'); let activeDatasetIndex = -1; const chart = new Chart(ctx, { type: 'bar', data: { labels: ['6月1日', '6月2日', '6月3日', '6月4日'], datasets: [/* 填入自己的基础数据集 */] }, options: { scales: { x: { stacked: true }, y: { stacked: true } }, onHover: (event, elements) => { const newIndex = elements.length ? elements[0].datasetIndex : -1; if (newIndex === activeDatasetIndex) return; activeDatasetIndex = newIndex; // 批量更新所有数据集样式 chart.data.datasets.forEach((dataset, index) => { const isActive = index === activeDatasetIndex; dataset.backgroundColor = isActive ? dataset.backgroundColor.replace('0.7', '1') : dataset.backgroundColor.replace('0.7', activeDatasetIndex === -1 ? '0.7' : '0.3'); dataset.borderColor = isActive ? '#222' : 'transparent'; dataset.borderWidth = isActive ? 2 : 0; dataset.offset = isActive ? 2 : 0; }); chart.update(); } } });
注意:如果使用Chart.js 3.0以下版本,不支持
offset属性,删除该配置即可,仅靠透明度和边框也可以满足高亮需求。
内容的提问来源于stack exchange,提问作者Saroopashree Kumaraguru
相关产品推荐
相关产品推荐

