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

如何在ECharts中实现带图例联动的堆叠柱状图总计展示

ECharts堆叠柱状图动态显示总计(图例切换自动更新)

问题描述

需要在每个堆叠柱状图上方显示总计数值,且当图例显示或隐藏时,总计数值能自动重新计算。

修改前效果:
修改前

修改后效果:
修改后

现有代码通过隐藏柱状图展示总计,但仅在初始化时计算一次,图例切换时总计不会更新,需要实现动态计算逻辑。

最佳实现方案

核心思路是监听ECharts的图例切换事件,在图例状态变化时实时计算当前显示系列的数值总和,再更新总计数据并刷新图表。具体步骤:

  • 移除初始化时的静态总计计算,改为动态计算逻辑
  • 监听legendselectchanged事件,捕获图例选中状态变化
  • 根据选中的图例过滤出参与计算的系列
  • 重新计算每个类别(Mon-Sun)的总和,更新总计系列数据
  • 调用setOption刷新图表

修改后的完整代码

// 初始化图表实例
const myChart = echarts.init(document.getElementById('main'));

const seriesData = [
    {
      name: 'Direct',
      type: 'bar',
      stack: 'total',
      label: {
        show: true
      },
      emphasis: {
        focus: 'series'
      },
      data: [320, 302, 301, 334, 390, 330, 320]
    },
    {
      name: 'Mail total',
      type: 'bar',
      stack: 'total',
      label: {
        show: true
      },
      emphasis: {
        focus: 'series'
      },
      data: [120, 132, 101, 134, 90, 230, 210]
    },
    {
      name: 'Affiliate total',
      type: 'bar',
      stack: 'total',
      label: {
        show: true
      },
      emphasis: {
        focus: 'series'
      },
      data: [220, 182, 191, 234, 290, 330, 310]
    },
    {
      name: 'Video total',
      type: 'bar',
      stack: 'total',
      label: {
        show: true
      },
      emphasis: {
        focus: 'series'
      },
      data: [150, 212, 201, 154, 190, 330, 410]
    },
    {
      name: 'Search Engine',
      type: 'bar',
      stack: 'total',
      label: {
        show: true
      },
      emphasis: {
        focus: 'series'
      },
      data: [820, 832, 901, 934, 1290, 1330, 1320]
    }
];

// 计算当前选中系列的总计
function calculateTotal(selectedLegends) {
    const totalArray = new Array(7).fill(0);
    seriesData.forEach(series => {
        if (selectedLegends[series.name]) {
            series.data.forEach((value, index) => {
                totalArray[index] += value;
            });
        }
    });
    return totalArray;
}

// 初始化选项
let option = {
  tooltip: {
    trigger: 'axis',
    axisPointer: {
      type: 'shadow',
      label:{
        formatter: function (params){
          let result = 0;
          params.seriesData.forEach(item => {
              if (item.seriesName !== '总计') {
                  result += item.value;
              }
          });
          return `${params.value} -------------------- total: ${result}`;
        }
      }
    }
  },
  legend: {
    data: seriesData.map(item => item.name),
  },
  grid: {
    left: '3%',
    right: '4%',
    bottom: '3%',
    containLabel: true
  },
  xAxis: {
    type: 'value'
  },
  yAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
  },
  series: [
    ...seriesData,
    {
      name: '总计',
      type: 'bar',
      tooltip: {
        show: false
      },
      stack: '',
      color: '#FFFFFF',
      label: {
        normal: {
          show: true,
          position: 'right',
          fontSize: 12,
          fontWeight: 'bold'
        },
      },
      data: calculateTotal(myChart.getOption().legend.selected),
      z: -1,
      barGap: '-100%',
    }
  ]
};

// 渲染图表
myChart.setOption(option);

// 监听图例切换事件
myChart.on('legendselectchanged', function(params) {
    const newTotal = calculateTotal(params.selected);
    myChart.setOption({
        series: [{
            name: '总计',
            data: newTotal
        }]
    });
});

// 响应窗口大小变化
window.addEventListener('resize', function() {
    myChart.resize();
});

关键代码解释

  • calculateTotal函数:接收当前选中的图例状态,仅对选中系列的数值求和,返回每个类别的总计数组。
  • 图例事件监听:通过legendselectchanged捕获状态变化,调用计算函数获取新总计数据,再通过setOption更新图表。
  • 初始化总计计算:首次渲染时,通过myChart.getOption().legend.selected获取初始选中状态,计算初始总计。

内容的提问来源于stack exchange,提问作者Cristian Aldo Novelli

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 20:40:48