You need to enable JavaScript to run this app. 如何在Chart.js及react-chartjs-2堆叠条形图中高亮所有条形的同一堆叠区段
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 00:21:03