chartsechartsapache-echarts

Wrong stacking of area chart (values added on x dimension)


I'm trying to create a chart with Apache ECharts that displays two line series (yVal1 and yVal2) and a range area (yVal2-yVal1) between them. However, when the range area is enabled, the chart behaves strangely. The lines become misaligned and the visualization breaks. When I disable the range area via legend, the remaining two lines display correctly.

Here's my configuration:

const testData = [
  { xVal: 167253120, yVal1: 10, yVal2: 20 },
  { xVal: 167253126, yVal1: 12, yVal2: 22 },
  { xVal: 167253132, yVal1: 8, yVal2: 25 },
  { xVal: 167253138, yVal1: 15, yVal2: 30 },
  { xVal: 167253144, yVal1: 18, yVal2: 28 },
  { xVal: 167253150, yVal1: 14, yVal2: 32 },
  { xVal: 167253156, yVal1: 20, yVal2: 35 },
  { xVal: 167253162, yVal1: 16, yVal2: 26 },
  { xVal: 167253168, yVal1: 22, yVal2: 38 },
  { xVal: 167253174, yVal1: 19, yVal2: 33 },
];

option = {
  title: {
    text: "Chart",
  },
  legend: {
    data: ["yVal1", "yVal2-yVal1", "yVal2"],
    top: 30,
  },
  xAxis: {
    type: "value",
    min: "dataMin",
    max: "dataMax",
  },
  yAxis: {
    type: "value",
  },
  series: [
    {
      name: "yVal1",
      type: "line",
      data: testData.map((item) => [item.xVal, item.yVal1]),
      symbol: "circle",
      stack: "range",
    },
    {
      name: "yVal2-yVal1",
      type: "line",
      data: testData.map((item) => [item.xVal, item.yVal2 - item.yVal1]),
      areaStyle: {
        color: "rgba(51, 152, 219, 0.3)",
      },
      symbol: "none",
      stack: "range",
    },
    {
      name: "yVal2",
      type: "line",
      data: testData.map((item) => [item.xVal, item.yVal2]),
      symbol: "circle",
    },
  ],
};

The issue:

Here's a live example demonstrating the problem: link to the example

What could be causing this behavior with the range area? Is there something wrong with my stacking configuration?

Expected behavior: all three series should display together with yVal2-yVal1 as a filled area between yVal1 and yVal2 lines


Solution

  • Yes, you're right, the issue is with stacking - the data is obviously stacked on the x axis, so the yVal2 - yVal1 series is represented at double its x values (its own x value plus the x value of the previous series in stack, yVal1).

    Echarts will stack data on its first dimension that is stackable, (see the source code) and that is x in your case, since x axis is a value axis.

    A possible solution is to put the data values in reverse order, and then use encode to map them to x and y:

    series: [
        {
            name: "yVal1",
            type: "line",
            data: testData.map((item) => [item.yVal1, item.xVal]),
            symbol: "circle",
            stack: "range",
            encode: {x: 1, y: 0}
        },
        {
            name: "yVal2-yVal1",
            type: "line",
            data: testData.map((item) => [item.yVal2 - item.yVal1, item.xVal]),
            areaStyle: {
                color: "rgba(51, 152, 219, 0.3)",
            },
            symbol: "none",
            stack: "range",
            encode: {x: 1, y: 0}
        },
        {
            name: "yVal2",
            type: "line",
            data: testData.map((item) => [item.yVal2, item.xVal]),
            symbol: "circle",
            encode: {x: 1, y: 0}
        },
    ],
    

    Modified echarts example.