I'm configuring two charts and the legend only appears when I use series.data
, but it doesn't appear when I use the dataset component (series.datasetIndex
and series.encode
). Nothing I tried worked. Here's the code:
document.addEventListener("DOMContentLoaded", () => {
// sytem
const chartSystem = () => {
return {
"source": {
"first": [
["name", "value"],
["Pressure", 40],
["Temperature", 64],
["Atmosphere", 89]
],
"second": [
["name", "value"],
["Label 1", 15],
["Label 2", 68]
]
}
}
}
// send
const pullDataset = [];
const pullData = [];
const chartSend = () => {
const { first, second } = chartSystem().source;
pullDataset.push({
source: first
// sourceHeader: true
});
pullData.push(
{
data: second.slice(1).map(([name, value]) => ({
name,
value
}))
}
);
};
chartSend();
// frames
const chartUse = echarts.init(document.getElementsByClassName("chart")[0]);
function chartFrameSwitch0 () {
const tooltip0 = {
show: true
};
const useDataLegend = pullDataset[0].source.slice(1).map(item => item[0]);
console.log(useDataLegend);
// legend
const legend0 = [
{
show: true,
data: useDataLegend,
borderWidth: 2,
borderColor: 'red'
},
{
show: true,
data: pullData[0].data.map(item => item.name),
borderWidth: 2,
borderColor: 'blue',
left: 'center',
top: '5%'
}
];
const grid0 = [
{
top: '30%',
left: '5%',
width: '38%',
height:'30%'
}
];
const xAxis0 = [
{
gridIndex: 0,
type: 'category'
}
];
const yAxis0 = [
{
gridIndex: 0,
type: 'value'
}
];
const series0 = [
{
type: 'bar',
color: ['#49a6de', '#ff7500', '#ff00ff'],
colorBy: 'data',
datasetIndex: 0,
encode: {
x: 0,
y: 1
},
xAxisIndex: 0,
yAxisIndex: 0
},
{
type: 'pie',
legendIndex: 0,
center: ['70%', '50%'],
data: pullData[0].data
}
];
const option = {
dataset: [pullDataset[0]],
legend: legend0, // Keep both legends in the array
tooltip: tooltip0,
grid: grid0,
xAxis: xAxis0,
yAxis: yAxis0,
series: series0
};
chartUse.setOption(option);
}
chartFrameSwitch0();
})
<head>
<script src='https://cdn.jsdelivr.net/npm/echarts@5.5.0/dist/echarts.min.js'></script>
</head>
<div class='chart' style='width: 100%; height: 100vh;'></div>
See the console.log of useDataLegend
:
[
"Pressure",
"Temperature",
"Atmosphere"
]
This is a manual way I tried to set legend.data: [...]
. I tried using series.encode
, but it doesn't seem to support setting the legend.
The issue is not related to the source of the data, the same
happens with the bar having a data
entry instead of encoding
.
The problem is actually with how legend works for a bar chart - in a bar chart (as well as many other types of charts) you simply can't have a legend entry for each data item, but one legend entry for each data set. That of course is not the case for the pie chart, where each data item (slice) will have its legend entry.
That has been the topic of this post and even if echarts has been updated a lot since then, this doesn't seem to have been changed.
There's also an important point about the meaning of legend.data
;
although the docs on legend.data
are a bit confusing, things
are clarified in legend.data.name
docs:
you can't put any name in there to alter the name that appears
for the legend. The string, (or the value of name
property if it's
an object) should be one of the actual names that appear by default
on the legend, that is the name
of a series for a bar chart and
the name
of a data item for a pie. A simple experiment will prove
that: replace in your code:
{
show: true,
data: pullData[0].data.map(item => item.name),
borderWidth: 2,
borderColor: 'blue',
left: 'center',
top: '5%'
}
the data
with an altered name, like
data: pullData[0].data.map(item => item.name + 'x'),
we see that the pie legend also disappears (jsfiddle).
Thus, the purpose of the names in data
is just to select the
legend items, for instance if a name of a series is missing, it
will not have a legend entry.
So, in order to have something displayed, in the bar legend
we have
to start by adding a name
to the bar series:
const series0 = [
{
type: 'bar',
name: 'barbar',
color: ['#49a6de', '#ff7500', '#ff00ff'],
colorBy: 'data',
...............
and add the same name in the corresponding legend.data
:
const legend0 = [
{
show: true,
data: ['barbar'], // or data: [{name: 'barbar'],
borderWidth: 2,
borderColor: 'red'
},
{
show: true,
data: pullData[0].data.map(item => item.name),
borderWidth: 2,
borderColor: 'blue',
left: 'center',
top: '10%'
}
]
This will put just one item in the red bordered legend, for the only bar series, jsFiddle.
It is important to select the items shown by the two legends through
legend.data
; if it were missing, the default for both legends would be to show all three available items, that is the one for the bar series and the two for the pie data items, (fiddle).
To achieve what you initially wanted, we have to employ the trick presented in the answer to the post linked above, that is to put each bar in its own series:
const chartSystem = () => {
return {
"source": {
"first": [
["name", "value"],
["Pressure", 40],
["Temperature", 64],
["Atmosphere", 89]
],
"second": [
["name", "value"],
["Label 1", 15],
["Label 2", 68]
]
}
}
}
// send
const pullDataset = [];
const pullData = [];
const header = [];
const chartSend = () => {
const { first, second } = chartSystem().source;
header.push(...first.slice(1).map(item => item[0]));
pullDataset.push({
source: [['name', ...header],
...Array.from({length: first.length - 1}, (_, i) =>
[header[i], ...Array.from({length: first.length - 1}, (_, j) => i === j ? first[i+1][1] : 0)])
]
});
pullData.push(
{
data: second.slice(1).map(([name, value]) => ({
name,
value
}))
}
);
};
chartSend();
// frames
const chartUse = echarts.init(document.getElementsByClassName("chart")[0]);
function chartFrameSwitch0 () {
const tooltip0 = {
show: true
};
const useDataLegend = pullDataset[0].source[0];
// legend
const legend0 = [
{
show: true,
borderWidth: 2,
data: header,
borderColor: 'red'
},
{
show: true,
data: pullData[0].data.map(item => item.name),
borderWidth: 2,
borderColor: 'blue',
left: 'center',
top: '10%'
}
];
const grid0 = [
{
top: '30%',
left: '5%',
width: '38%',
height:'30%'
}
];
const xAxis0 = [
{
gridIndex: 0,
type: 'category',
//data: header
}
];
const yAxis0 = [
{
gridIndex: 0,
type: 'value'
}
];
const colors = ['#49a6de', '#ff7500', '#ff00ff'];
const series0 = pullDataset[0].source.slice(1).map((item, idx) => ({
type: 'bar',
name: header[idx],
color: colors[idx],
stack: 'stack',
encode: {
x: 0,
y: idx+1
},
xAxisIndex: 0,
yAxisIndex: 0
})).concat([{
type: 'pie',
center: ['70%', '50%'],
data: pullData[0].data
}]);
const option = {
dataset: pullDataset[0],
legend: legend0, // Keep both legends in the array
tooltip: tooltip0,
grid: grid0,
xAxis: xAxis0,
yAxis: yAxis0,
series: series0
};
chartUse.setOption(option);
}
chartFrameSwitch0();
<div class='chart' style='height: 300px'></div>
<script src="https://cdn.jsdelivr.net/npm/echarts@5.5.1/dist/echarts.min.js"></script>
(or as jsFiddle).