set different bar width for each bar using ECHARTS

Viewed 331

Im using the e-charts libary for creating a bar chart for my data . like so :

option.series = [
        {
            name: 'buy',
            type: 'bar',
            stack: 'one',
            data: Object.values(chartData?.data || {}).map(elem => -elem.buy?.total),
            color: colors.bought,
            label: {
                show: true,
                position: "bottom",
                formatter: (value) => Math.round(Math.abs(value.data))
            },
            tooltip: {
                formatter: (data) => Math.abs(data.value).toString()
            },
            // barWidth:this.data
        },
        {
            name: 'sell',
            type: 'bar',
            stack: 'one',
            data: Object.values(chartData?.data || {}).map(elem =>elem.sell?.total),
            color: colors.sold,
            label: {
                show: true,
                position: "top",
                formatter: (value) => Math.round(Math.abs(value.data))
            },
            tooltip: {
                formatter: (data) => Math.abs(data.value).toString()
            },
        },
        {
            name: 'profite',
            type: 'bar',
            stack: 'two',
            barGap: '-100%',  
            z: 100,
            data: Object.values(chartData?.data || {}).map(elem => elem.sell?.profit),
            color: colors.profit,
            label: {
                show: true,
                position: "insideTop",
                textBorderWidth: -1,
                offset: [0, -20],
                formatter: (value) => Math.round(Math.abs(value.data))
            },
            tooltip: {
                formatter: (data) => Math.abs(data.value).toString()
            },
        },
    ]

im trying to set a different width for each bar depending on the value of each bar . on data property i get a list of numbers rendering . When i try to add a barWidth property all i can do is change all of the bars in the same chrts like so for example:

barWidth: ${getBarWidth((Object.values(chartData?.data || {}).map((elem) => elem.sell?.amount)))}%

so i returne a different value of my data each time but it didnt changed each bar according to its value (either buy, sell and so on).

Thanks in adavance.

1 Answers

As you pointed out, barWidth sets the width of all the bars of a bar series. And I don't think there is a way to set the width of each bar in the same bar series.

What you should use instead is a custom series.

Custom series have a parameter called renderItem, where you write the render logic of the chart. It's where you'll be able to display custom shapes (custom sized bar in your case), using graphics.

Here is an example I found on their website, doing pretty much what you're looking for.

var container = document.getElementById('main');
var chart = echarts.init(container);

const colorList = [
  '#4f81bd',
  '#c0504d',
  '#9bbb59',
  '#604a7b',
  '#948a54',
  '#e46c0b'
];
const data = [
  [10, 16, 3, 'A'],
  [16, 18, 15, 'B'],
  [18, 26, 12, 'C'],
  [26, 32, 22, 'D'],
  [32, 56, 7, 'E'],
  [56, 62, 17, 'F']
].map(function (item, index) {
  return {
    value: item,
    itemStyle: {
      color: colorList[index]
    }
  };
});

chart.setOption({
  title: {
    text: 'Profit',
    left: 'center'
  },
  tooltip: {},
  xAxis: {
    scale: true
  },
  yAxis: {},
  series: [
    {
      type: 'custom',
      renderItem: function (params, api) {
        var yValue = api.value(2);
        var start = api.coord([api.value(0), yValue]);
        var size = api.size([api.value(1) - api.value(0), yValue]);
        var style = api.style();
        return {
          type: 'rect',
          shape: {
            x: start[0],
            y: start[1],
            width: size[0],
            height: size[1]
          },
          style: style
        };
      },
      label: {
        show: true,
        position: 'top'
      },
      dimensions: ['from', 'to', 'profit'],
      encode: {
        x: [0, 1],
        y: 2,
        tooltip: [0, 1, 2],
        itemName: 3
      },
      data: data
    }
  ]
});
#main {
  width: 600px;
  height: 400px;
}
<html>
  <body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.3.2/echarts.min.js"></script>
    <div id="main"></div>
  </body>
</html>

Related