How to display sum stack bar in echarts with legend handling

Viewed 46

What I need is to show the totals above each column and for the total to be recalculated as the legend is shown or hidden. What is the best practice to do this?

Before:

enter image description here

After:

enter image description here

In this code example the total is calculated through a bar below those that are generated through echart, what I want to achieve is that the total of the bar below is recalculated every time the legend is modified

let result = 0;
let array = [];

const series = [
    {
      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]
    },
  ];
  
  sum()

option = {
  tooltip: {
    trigger: 'axis',
    axisPointer: {
      // Use axis to trigger tooltip
      type: 'shadow', // 'shtotalow' as default; can also be 'line' or 'shtotalow'
      label:{
        formatter: function (params){
          for ( let i = 0; i < params.seriesData.length-1; i++){
            result += params.seriesData[i].value
          } 
          let resultFinal = params.value + " -------------------- total: " + result
          result = 0;
          return resultFinal;
        }
      }
    }
  },
      legend: {
        data: series.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: [
    {
      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]
    },
    {
    
      name: ' A total of ',
      type: 'bar',
      tooltip: {
        show: false
      },
      stack: '',
      color: '#FFFFFF',
      label: {
        normal: {
          show: true,
          position: 'right'
        },
      },
      data: array,
      z: -1,
      barGap: '-100%',
    }
  ]
};


function sum(){
  for ( let z = 0; z < series[0].data.length; z++){
    for( let i = 0; i < series.length; i++){
    result += series[i].data[z];
  }
  array.push(result)
  result = 0;
  }
}
1 Answers

The solution is to detect when the legend is clicked/changed, by using 'legendselectchanged' event. Once the legend is changed, you can recalculate the array of results and then push this new array to your chart.

Add the following code to the example you gave and it'll work. (Working example)

myChart.on('legendselectchanged', function (params) {
  array.length = 0
  for ( let z = 0; z < series[0].data.length; z++){
    for( let i = 0; i < series.length; i++){
      if(params.selected[series[i].name])
        result += series[i].data[z];
    }
    array.push(result)
    result = 0;
  }
  myChart.setOption(option);
});
Related