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

Chart.js堆叠分组柱状图标签重复问题解决咨询

解决Chart.js分组堆叠柱状图的图例重复问题

一、先调整数据集结构(关键前提)

动态生成数据集时,给每个数据集添加自定义元数据,比如category(标记是dogs还是cats)和year(标记是2022还是2023),后续处理图例时就能精准识别分组逻辑。示例数据集结构如下:

const datasets = [
  {
    label: '2022-dogs',
    data: [10, 15, 8],
    stack: '2022', // 同一年份的数据集归为一个堆叠组
    backgroundColor: '#ff6384',
    category: 'dogs', // 自定义属性:类别
    year: '2022' // 自定义属性:年份
  },
  {
    label: '2022-cats',
    data: [5, 9, 12],
    stack: '2022',
    backgroundColor: '#36a2eb',
    category: 'cats',
    year: '2022'
  },
  {
    label: '2023-dogs',
    data: [12, 18, 10],
    stack: '2023',
    backgroundColor: '#ff6384', // 同类别用统一颜色
    category: 'dogs',
    year: '2023'
  },
  {
    label: '2023-cats',
    data: [7, 11, 14],
    stack: '2023',
    backgroundColor: '#36a2eb',
    category: 'cats',
    year: '2023'
  }
];

二、用generateLabels生成自定义图例

通过这个方法提取唯一的category和year值,生成你需要的dogs、cats、2022、2023四个图例项,同时保留对应颜色,还要配套处理图例点击逻辑:

options: {
  plugins: {
    legend: {
      labels: {
        generateLabels: function(chart) {
          const uniqueItems = new Map();
          // 提取所有唯一的类别和年份
          chart.data.datasets.forEach(ds => {
            // 添加类别项
            if (!uniqueItems.has(`category-${ds.category}`)) {
              uniqueItems.set(`category-${ds.category}`, {
                text: ds.category,
                fillStyle: ds.backgroundColor,
                category: ds.category
              });
            }
            // 添加年份项
            if (!uniqueItems.has(`year-${ds.year}`)) {
              // 年份可以用统一颜色,这里用灰色示例
              uniqueItems.set(`year-${ds.year}`, {
                text: ds.year,
                fillStyle: '#cccccc',
                year: ds.year
              });
            }
          });
          // 转换为数组返回
          return Array.from(uniqueItems.values());
        }
      },
      // 处理图例点击:点击类别切换所有同类别数据集,点击年份切换同年份所有数据集
      onClick: function(event, legendItem) {
        const chart = this.chart;
        if (legendItem.category) {
          chart.data.datasets.forEach(ds => {
            if (ds.category === legendItem.category) {
              ds.hidden = !ds.hidden;
            }
          });
        } else if (legendItem.year) {
          chart.data.datasets.forEach(ds => {
            if (ds.year === legendItem.year) {
              ds.hidden = !ds.hidden;
            }
          });
        }
        chart.update();
      }
    }
  },
  scales: {
    x: {
      stacked: true, // X轴堆叠实现分组内堆叠
      ticks: {
        labels: ['1月', '2月', '3月'] // 动态生成月份标签即可
      }
    },
    y: {
      stacked: true // Y轴堆叠
    }
  }
}

三、为什么之前的filter方法没生效?

默认的filter只是针对单个数据集的图例项做过滤,没法合并重复项生成你要的四个图例。要实现需求,必须用generateLabels重新生成图例结构,再配合onClick处理交互逻辑。

四、动态场景适配

只要动态生成数据集时,给每个数据集带上category和year属性,上面的代码就能自动提取唯一值,完全不需要硬编码类别或年份,适配你的动态生成需求。

内容的提问来源于stack exchange,提问作者Joao Moleiro

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 20:42:24