如何在 echarts 堆叠条形图的顶部添加总和 [根据所选系列更新]
How can I add a sum at the top of an echarts stacked bar chart [which updates based on selected series]
关于如何在 echarts 上的堆叠条形图顶部添加 'total' 标签的问题已经得到解答(例如 this one)
但是,我还希望在使用图例 selected/deselected 系列时重新计算此总数(包括如果我在下面的示例中取消选择标签所附加的最终系列)。这可能吗?
另一个问题的示例代码:
//example data
this.mySeries = [{
name: 'Dataset 1',
type: 'bar',
stack: 'Stack 1',
data: [120, 132, 101, 134, 90, 230, 210]
},
{
name: 'Dataset 2',
type: 'bar',
stack: 'Stack 1',
data: [220, 182, 191, 234, 290, 330, 310]
},
{
name: 'Dataset 3',
type: 'bar',
stack: 'Stack 1',
data: [820, 932, 901, 934, 1290, 1330, 1320],
}
];
//function for formatter
genFormatter = (series) => {
return (param) => {
console.log(param);
let sum = 0;
series.forEach(item => {
sum += item.data[param.dataIndex];
});
return sum
}
};
//inside your chart options place this
series: series.map((item, index) => Object.assign(item, {
type: 'bar',
stack: true,
label: {
show: index === series.length - 1,
formatter: genFormatter(series),
fontSize: 20,
color: 'black',
position: 'top'
},
})),
是的,这是可能的。您需要添加处理程序,以便在图例中的选定系列发生变化时进行监听。参见 legendselectchanged 事件。
在您的事件处理程序中,您需要过滤选择了哪些系列并重新计算总和,然后将标签附加到最后一个系列。
为了将总和标签附加到最后一个系列,您可以创建这样的函数:
const seriesHandler = series => {
return series.map((serie, index) => {
if (index === series.length - 1) {
return {
...serie,
label: {
normal: {
show: true,
position: 'top',
formatter: params => {
let total = 0
series.forEach(s => {
total += s.data[params.dataIndex]
})
return total
}
}
}
}
} else {
return serie
}
})
}
并像这样创建 legendselectchanged 事件处理程序:
const handleLegendSelectChanged = (event, series) => {
const includedSeriesNames = []
for (const [name, value] of Object.entries(event.selected)) {
if (value) {
includedSeriesNames.push(name)
}
}
const includedSeries = series.filter(serie => {
return includedSeriesNames.includes(serie.name)
})
return seriesHandler(includedSeries)
}
基本上它过滤显示(包括)哪个系列,并将总和标签附加到最后一个系列。
请参阅下面的完整示例:
<!DOCTYPE html>
<html style="height: 100%">
<head>
<meta charset="utf-8">
</head>
<body style="height: 100%; margin: 0">
<div id="container" style="height: 100%"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/4.8.0/echarts.js"
integrity="sha512-5/8+cwsZ4fICxk706J4H0/UMZT2LKivISN26mgN86wCD4AHFvdFOBm/95z3dKLpnaHNzzwKuoBtrbKv+++SLTg=="
crossorigin="anonymous"></script>
<script type="text/javascript">
const mySeries = [
{
name: 'Dataset 1',
type: 'bar',
stack: 'Stack 1',
data: [120, 132, 101, 134, 90, 230, 210]
},
{
name: 'Dataset 2',
type: 'bar',
stack: 'Stack 1',
data: [220, 182, 191, 234, 290, 330, 310]
},
{
name: 'Dataset 3',
type: 'bar',
stack: 'Stack 1',
data: [820, 932, 901, 934, 1290, 1330, 1320],
}
];
const seriesHandler = series => {
return series.map((serie, index) => {
if (index === series.length - 1) {
return {
...serie,
label: {
normal: {
show: true,
position: 'top',
formatter: params => {
let total = 0
series.forEach(s => {
total += s.data[params.dataIndex]
})
return total
}
}
}
}
} else {
return serie
}
})
}
const handleLegendSelectChanged = (event, series) => {
const includedSeriesNames = []
for (const [name, value] of Object.entries(event.selected)) {
if (value) {
includedSeriesNames.push(name)
}
}
const includedSeries = series.filter(serie => {
return includedSeriesNames.includes(serie.name)
})
return seriesHandler(includedSeries)
}
const dom = document.getElementById("container");
const myChart = echarts.init(dom);
const option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
toolbox: {
show: true,
orient: 'vertical',
left: 'right',
top: 'center',
feature: {
dataView: { show: false, readOnly: false },
magicType: { show: true, type: ['line', 'bar', 'stack', 'tiled'] },
restore: { show: true },
saveAsImage: { show: true }
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
yAxis: {
type: 'value'
},
xAxis: {
type: 'category',
data: ["Jen\n2018", "Feb\n2018", "Mar\n2018", "Apr\n2018", "May\n2018", "Jun\n2018", "Jul\n2018"]
},
legend: {
data: ['Dataset 1', 'Dataset 2', 'Dataset 3']
},
};;
myChart.setOption({
...option,
series: seriesHandler(mySeries)
})
myChart.on('legendselectchanged', event => {
myChart.setOption({
series: handleLegendSelectChanged(event, mySeries)
})
})
</script>
</body>
</html>
关于如何在 echarts 上的堆叠条形图顶部添加 'total' 标签的问题已经得到解答(例如 this one)
但是,我还希望在使用图例 selected/deselected 系列时重新计算此总数(包括如果我在下面的示例中取消选择标签所附加的最终系列)。这可能吗?
另一个问题的示例代码:
//example data
this.mySeries = [{
name: 'Dataset 1',
type: 'bar',
stack: 'Stack 1',
data: [120, 132, 101, 134, 90, 230, 210]
},
{
name: 'Dataset 2',
type: 'bar',
stack: 'Stack 1',
data: [220, 182, 191, 234, 290, 330, 310]
},
{
name: 'Dataset 3',
type: 'bar',
stack: 'Stack 1',
data: [820, 932, 901, 934, 1290, 1330, 1320],
}
];
//function for formatter
genFormatter = (series) => {
return (param) => {
console.log(param);
let sum = 0;
series.forEach(item => {
sum += item.data[param.dataIndex];
});
return sum
}
};
//inside your chart options place this
series: series.map((item, index) => Object.assign(item, {
type: 'bar',
stack: true,
label: {
show: index === series.length - 1,
formatter: genFormatter(series),
fontSize: 20,
color: 'black',
position: 'top'
},
})),
是的,这是可能的。您需要添加处理程序,以便在图例中的选定系列发生变化时进行监听。参见 legendselectchanged 事件。
在您的事件处理程序中,您需要过滤选择了哪些系列并重新计算总和,然后将标签附加到最后一个系列。
为了将总和标签附加到最后一个系列,您可以创建这样的函数:
const seriesHandler = series => {
return series.map((serie, index) => {
if (index === series.length - 1) {
return {
...serie,
label: {
normal: {
show: true,
position: 'top',
formatter: params => {
let total = 0
series.forEach(s => {
total += s.data[params.dataIndex]
})
return total
}
}
}
}
} else {
return serie
}
})
}
并像这样创建 legendselectchanged 事件处理程序:
const handleLegendSelectChanged = (event, series) => {
const includedSeriesNames = []
for (const [name, value] of Object.entries(event.selected)) {
if (value) {
includedSeriesNames.push(name)
}
}
const includedSeries = series.filter(serie => {
return includedSeriesNames.includes(serie.name)
})
return seriesHandler(includedSeries)
}
基本上它过滤显示(包括)哪个系列,并将总和标签附加到最后一个系列。
请参阅下面的完整示例:
<!DOCTYPE html>
<html style="height: 100%">
<head>
<meta charset="utf-8">
</head>
<body style="height: 100%; margin: 0">
<div id="container" style="height: 100%"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/4.8.0/echarts.js"
integrity="sha512-5/8+cwsZ4fICxk706J4H0/UMZT2LKivISN26mgN86wCD4AHFvdFOBm/95z3dKLpnaHNzzwKuoBtrbKv+++SLTg=="
crossorigin="anonymous"></script>
<script type="text/javascript">
const mySeries = [
{
name: 'Dataset 1',
type: 'bar',
stack: 'Stack 1',
data: [120, 132, 101, 134, 90, 230, 210]
},
{
name: 'Dataset 2',
type: 'bar',
stack: 'Stack 1',
data: [220, 182, 191, 234, 290, 330, 310]
},
{
name: 'Dataset 3',
type: 'bar',
stack: 'Stack 1',
data: [820, 932, 901, 934, 1290, 1330, 1320],
}
];
const seriesHandler = series => {
return series.map((serie, index) => {
if (index === series.length - 1) {
return {
...serie,
label: {
normal: {
show: true,
position: 'top',
formatter: params => {
let total = 0
series.forEach(s => {
total += s.data[params.dataIndex]
})
return total
}
}
}
}
} else {
return serie
}
})
}
const handleLegendSelectChanged = (event, series) => {
const includedSeriesNames = []
for (const [name, value] of Object.entries(event.selected)) {
if (value) {
includedSeriesNames.push(name)
}
}
const includedSeries = series.filter(serie => {
return includedSeriesNames.includes(serie.name)
})
return seriesHandler(includedSeries)
}
const dom = document.getElementById("container");
const myChart = echarts.init(dom);
const option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
toolbox: {
show: true,
orient: 'vertical',
left: 'right',
top: 'center',
feature: {
dataView: { show: false, readOnly: false },
magicType: { show: true, type: ['line', 'bar', 'stack', 'tiled'] },
restore: { show: true },
saveAsImage: { show: true }
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
yAxis: {
type: 'value'
},
xAxis: {
type: 'category',
data: ["Jen\n2018", "Feb\n2018", "Mar\n2018", "Apr\n2018", "May\n2018", "Jun\n2018", "Jul\n2018"]
},
legend: {
data: ['Dataset 1', 'Dataset 2', 'Dataset 3']
},
};;
myChart.setOption({
...option,
series: seriesHandler(mySeries)
})
myChart.on('legendselectchanged', event => {
myChart.setOption({
series: handleLegendSelectChanged(event, mySeries)
})
})
</script>
</body>
</html>