背景
最近在实现一个柱状图图表展示的需求,需要实现一个设备状态的展示,要求每个柱子颜色不一样,并且有像多系列柱状图的图例效果,就像下面这样:

查了下Echarts的官方示例,发现实现了图例的都是多系列的,比如这种每个X轴子项有两个或两个以上的多系统柱状图:

实践
于是只能看看官方文档的api,第一个首先要实现修改柱子的颜色,这个比较简单,只需修改图表的option属性里的series里的itemStyle即可
css
option = {
xAxis: {
type: 'category',
data: ['Vue', 'React', 'Angular']
},
yAxis: {
type: 'value'
},
series: [
{
data: [
120,
{
value: 200,
itemStyle: {
color: '#a90000'
}
},
150,
],
type: 'bar'
}
]
};
接下来只要给它加上legend属性(用于设置图例)就可以了是吗?让我们来试试
option
xAxis: {
type: 'category',
data: ['Vue', 'React', 'Angular']
},
yAxis: {
type: 'value'
},
legend: {
// 可以留空,自动从 series.name 获取
},
series: [
{
name: '图例', // 必须加 name
data: [120, { value: 200, itemStyle: { color: '#a90000' } }, 150],
type: 'bar'
}
]
};
照着上面这个代码设置legend,你会发现series里的name只有一个,但是x轴有三项,数量对不上,并且点击图例后是三个子项一起消失和出现。原因就是legend是和series里每一个子项一一对应的,但是我们只有一个系列,所以就会出现这种一齐消失出现的情况了。
解决方法
看到这里,是不是已经有了一点点思绪了。没错!就是要通过障眼法设置多个系列,将在每个X轴子项上的原本的多个系列展示成只显示一个,只需将其他系列的值设置为0,留下当前系列的值,由于原本是三个系列占一个X轴子项的宽度,现在只在一个X轴子项上显示一个,所以需要再调整一下其宽度即可~
下面是完整代码展示
xml
<template>
<div class="home-index">
<div class="echarts_Statistics">
<div ref="chartRef"></div>
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted, reactive, ref, nextTick } from "vue";
import * as echarts from "echarts";
const chartRef = ref<any>(null);
const chart = ref<any>(null)
const series = ref<any>([])
const option = reactive({
title:{
text:"统计",
left:'70'
},
legend: {
data: [
{
name: 'Vue',
icon: 'rect'
},
{
name: 'React',
icon: 'rect'
},
{
name: 'Angular',
icon: 'rect'
}
],
},
xAxis: {
type: "category",
data: ["Vue", "React", "Angular"],
},
yAxis: {
type: "value",
},
series,
});
const getData = async () => {
try {
const res = await new Promise<any>((resolve) => {
setTimeout(() => {
resolve({
'Vue':1,
'React':2,
'Angular':3
});
}, 0);
});
// 图例实现核心:
series.value = [
{
name: 'Vue',
type: 'bar',
data: [res['Vue'], 0, 0],
itemStyle: {
color: '#00A900' // 蓝色
},
barWidth: '60%', // 确保柱子宽度正常
barGap: '-100%' // 核心:让所有系列在同一类目下完全重叠
},
{
name: 'React',
type: 'bar',
data: [0,res['React'], 0],
itemStyle: {
color: 'rgba(230,162,60)'
},
barWidth: '60%',
barGap: '-100%'
},
{
name: 'Angular',
type: 'bar',
data: [0,0,res['Angular']],
itemStyle: {
color: 'rgba(255,0,0)'
},
barWidth: '60%',
barGap: '-100%'
}
]
chart.value.setOption(option);
}
catch (error) {
console.log(error)
}
}
onMounted(() => {
chart.value = echarts.init(chartRef.value);
// 这里需要首先setOption,保证坐标轴等基础配置能够正确显示
chart.value.setOption(option)
getData();
});
</script>
<style scoped lang="scss">
.home-index {
height: 100%;
width: 100%;
padding: 20px 20px 10px 20px;
border-radius: 6px;
.echarts_Statistics {
width: 100%;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
div {
width: 45%;
height: 300px;
}
}
}
</style>