Overflowing bar serie in apache echarts when using dataZoom

113 Views Asked by At

I am using apache echarts version 5.2.2 for rendering a bar chart with datazooms for both cartesian axes. However I am finding an easy to reproduce bug with this code that can be found just in the dataZoom documentation.

enter image description here

That is what happens when I apply an inside zoom to my bars, it ends up overflowing the space for the Y axis.

The code that produces this is the following, which can be pasted in the echarts example page:

option = {
    dataZoom: [
        {
            id: 'dataZoomX',
            type: 'inside',
            xAxisIndex: [0],
            filterMode: 'filter'
        },
        {
            id: 'dataZoomY',
            type: 'inside',
            yAxisIndex: [0],
            filterMode: 'empty'
        }
    ],
    xAxis: {type: 'value'},
    yAxis: {type: 'value'},
    series: {
        type: 'bar',
        data: [
            // The first column corresponds to xAxis,
            // and the second column corresponds to yAxis.
            [12, 24, 36],
            [90, 80, 70],
            [3, 9, 27],
            [1, 11, 111]
        ]
    }
}

I have read the suggested configurations for the filterMode property, but this bug happens whether if I use filter, weakFilter, etc. I have also seen this work properly for other charts that have an X axis of type category, but mine is of type value and the inside zooms are mandatory.

Am I missing something? Thanks for your help.

1

There are 1 best solutions below

0
On

Seems like echarts places the bars as long as the center is inside the grid. I dont see an inbuild way around that currently. Here are some possible suggestions:

  1. Use a combination of barMaxWidth and yAxis offset to make space between bars and the yAxis. (Note, that for some reason a second yAxis is neccessary for offset to work properly).

Example:

option = {
  dataZoom: [
    {
      id: 'dataZoomX',
      type: 'inside',
      xAxisIndex: [0],
      filterMode: 'filter'
    },
    {
      id: 'dataZoomY',
      type: 'inside',
      yAxisIndex: [1],
      filterMode: 'empty'
    }
  ],
  xAxis: { type: 'value' },
  yAxis: [{ show: false }, { position: 'left', offset: 20 }],
  series: {
    type: 'bar',
    yAxisIndex: 1,
    barMaxWidth: 40,
    data: [[12, 24],[90, 80],[3, 9],[1, 11]]
  }
};
  1. Use the dataZoom event to adjust the data by yourself if its overlapping the axis.

Example:

const data = [{value: [1, 11]},{value: [3, 9]},{value: [12, 24]},{value: [90, 80]}];

option = {
  dataZoom: [
    {
      id: 'dataZoomX',
      type: 'inside',
      xAxisIndex: [0],
      filterMode: 'filter'
    },
    {
      id: 'dataZoomY',
      type: 'inside',
      yAxisIndex: [1],
      filterMode: 'empty'
    }
  ],
  xAxis: {},
  yAxis: {},
  series: {
    type: 'bar',
    data: data,
  }
};


myChart.on('dataZoom', function(params) {
  const components = myChart._componentsMap;
  const xAxis = components[Object.keys(components).find(key => key.includes('xAxis'))];
  const start = xAxis.__model.axis.scale._extent[0];
  const series = Object.values(myChart._chartsMap)[0];
  
  const originPixel = myChart.convertToPixel({xAxisIndex: 0}, start);
  const barWidthPixel = series._data._layout.size;
  
  const newData = [];
  for (const datapoint of data) {
    const barCenterpixel = myChart.convertToPixel({xAxisIndex: 0}, datapoint.value[0]);
    if (barCenterpixel - (barWidthPixel / 2) > originPixel) {
      datapoint.itemStyle = undefined;
    } else {
      datapoint.itemStyle = {color: 'transparent'};
    }
    newData.push(datapoint);
  }
  
  myChart.setOption({series: [{data: newData}]});
})