需求开发一个饼状图,要求:点击右侧的模块,左侧饼状图对应的变化
效果如下:
遇到的问题:
在实际项目开发过程中,碰到了一个棘手的问题,那就是,右侧显示的legend模块后面的数字显示不是 很好做,因为在echarts配置项option里,左侧的tooltip里的模块名name 是和右侧legend显示的值是对应的,这么说不太好理解,举个例子,例如,如下截图
显然,tooltip中的模块title不能这么显示,但是echarts里面的默认配置就是这样,如果想做成 legend显示 模块名+数字,tooltip弹框里只显示 模块名的话,就需要用到 legend 里的formatter属性了,但是使用formatter的过程中,会碰到一个问题 ,那就是不是很好动态传值到formatter函数里面,我是这么解决的
生命一个常量optionData,给它传值,然后,放到 设置 legend属性之前,这样,formatter 李曼就能直接使用外面传进去的值了
this.optionData = this.option.series[0].data;
// 赋值给常量 optionData
const optionData = this.optionData;
this.option.legend = {
formatter(params) { // params 是模块的名字
if (optionData.length) {
// 这里的optionData就是外面的常量的值,我是拼了一个数组传进来的
// 然后这里根据模块名的值,也就是params的值,动态的拼成自己想要的显示样子
switch (params) {
case "Very High Risk":
return params + " " + optionData[0].value;
break;
case "High Risk":
return params + " " + optionData[1].value;
break;
case "Medium Risk":
return params + " " + optionData[2].value;
break;
case "Low Risk":
return params + " " + optionData[3].value;
break;
case "Very Low Risk":
return params + " " + optionData[4].value;
break;
default:
return "";
}
}
}
上代码
<template>
<div
id="leftEchartPie"
ref="leftEchartPie"
></div>
</template>
<script>
export default {
props: {
leftPieData: {
type: Object,
default: {}
}
},
data() {
return {
myChart: null,
option: null,
optionData: []
};
},
watch: {
leftPieData: {
// immediate: true,
deep: true,
handler(leftPieData) {
if (leftPieData) {
this.initChart(leftPieData);
}
}
}
},
mounted() {
const option = {
title: {
zlevel: 0,
text: null,
rich: {
value: {
color: "#3F495A",
fontSize: 14,
lineHeight: 16
},
name: {
color: "#3F495A",
fontSize: 14,
lineHeight: 16
}
},
top: "center",
left: "30%",
textAlign: "center",
textStyle: {
rich: {
value: {
color: "#3F495A",
fontSize: 14,
lineHeight: 16
},
name: {
color: "#3F495A",
lineHeight: 16
}
}
}
},
tooltip: {
show: true,
trigger: "item",
formatter: "{a}
{b}: {c} ({d}%)"
},
legend: {},
series: [
{
name: "Security Status",
type: "pie",
center: ["30%", "50%"],
radius: ["80%", "45%"],
itemStyle: {
borderWidth: 6,
borderColor: "#fff"
},
hoverAnimation: false,
avoidLabelOverlap: false,
label: {
show: false,
position: "center"
},
emphasis: {
label: {
show: false,
fontSize: "30",
fontWeight: "bold"
}
},
labelLine: {
show: false
},
data: []
}
]
};
this.option = option;
var dom = document.getElementById("leftEchartPie");
var myChart = this.echarts.init(dom);
this.myChart = myChart;
let that = this;
// 监听resize
window.addEventListener("resize", function() {
that.mychart.resize();
});
},
methods: {
initChart(leftPieData) {
this.option.text = [
"{name|Total}",
"{value|" + leftPieData.totalNum + "}"
].join("\n");
this.option.legend.data = [
`Very High Risk`,
`High Risk`,
`Medium Risk`,
`Low Risk`,
`Very Low Risk`
];
this.option.series[0].data = [
{
value: this.leftPieData.veryHighRiskNum,
name: `Very High Risk`,
itemStyle: {
color: "#FF4D4F"
}
},
{
value: this.leftPieData.highRiskNum,
name: `High Risk`,
itemStyle: {
color: "#FA9314"
}
},
{
value: this.leftPieData.mediumRiskNum,
name: `Medium Risk`,
itemStyle: {
color: "#FACB14"
}
},
{
value: this.leftPieData.lowRiskNum,
name: `Low Risk`,
itemStyle: {
color: "#4ED6CC"
}
},
{
value: this.leftPieData.veryLowNum,
name: `Very Low Risk`,
itemStyle: {
color: "#2BD374"
}
}
];
this.optionData = this.option.series[0].data;
const optionData = this.optionData;
this.option.legend = {
orient: "vertical",
left: "60%",
top: "middle",
icon: "circle",
itemHeight: 7, //改变圆圈大小
// data: [],
formatter(params) {
if (optionData.length) {
switch (params) {
case "Very High Risk":
return params + " " + optionData[0].value;
break;
case "High Risk":
return params + " " + optionData[1].value;
break;
case "Medium Risk":
return params + " " + optionData[2].value;
break;
case "Low Risk":
return params + " " + optionData[3].value;
break;
case "Very Low Risk":
return params + " " + optionData[4].value;
break;
default:
return "";
}
}
}
};
// 绘制图表
this.myChart.setOption(this.option);
}
}
};
</script>
<style>
#leftEchartPie {
width: 100%;
height: calc(100% - 60px);
}
</style>