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
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}
},
],