最近做项目遇到这样一个场景,有一个标签选择界面,选择不同的标签需要展示不同的图表有可能折线图,有可能柱状图,也可能饼图,图表的类型由后端返回,标签可以多选。这个时候就需要动态来渲染不定数量和类型的echarts图表了。
第一步,选择标签
将选择的所有标签存储到downloadCheckList数组中,再添加一个数组editableTabs用来存放需要展示的标签的相关信息。obj1代表发送请求时需要携带的参数,obj也需要携带,处理数据会用到。同时初始化echarts图表。
//选择标签完成
selecttrue(val) {
let that=this
// 每次选择标签完成创建echarts实例,
if(val==2){
//遍历整理信息
for (let i in that.downloadCheckList) {
let obj = {
title: that.downloadCheckList[i],//图表名字
id: "chart" + i, //图表id
chart: null, //用来存储图表实例
name: i, //每个图表对应的顺序
};
let obj1={
timeScope:"$timeScope"
}
obj1[that.downloadCheckList[i]]=`$${ that.downloadCheckList[i]}`
that.editableTabs.push(obj);
//发送ajax请求
that.getDataFromLabel(obj1,that.Time[0], that.Time[1],obj);
}
//分配初始化图表
that.chartInit();
}else{
// 切换时间不需要执行chartInit()创建echarts实例
for (let i in that.editableTabs) {
let obj = that.editableTabs[i]
let obj1={
timeScope:"$timeScope"
}
obj1[that.editableTabs[i].title]=`$${ that.editableTabs[i].title}`
that.getDataFromLabel(obj1, that.Time[0], that.Time[1],obj);
}
}
}
// 分配初始化图表
chartInit() {
let that = this;
this.$nextTick(() => {
//动态获取宽高
let WH=document.getElementById('WH').childNodes[0]
for (let i in that.editableTabs) {
that.editableTabs[i].chart = that.$echarts.init(document.getElementById(that.editableTabs[i].id));
}
that.width =parseInt(window.getComputedStyle(WH,null).width)-14+'px'
that.height =parseInt(window.getComputedStyle(WH,null).height)-10+'px'
});
},
HTML部分使用v-for 遍历 editableTabs数组代表需要展示的图表。这里使用动态宽高来适应不同屏幕尺寸。
<div v-for="item in editableTabs" id='WH' :key="item.id">
<div :style="{ width:width,height:height}" :id="item.id" :ref="item.id">{
{item.title}}</div>
</div>
</div>
第二步 处理服务端返回的数据
请求完成后执行 setdatalabel() 方法处理数据,data为服务端返回的数据,obj为请求时携带的标签信息,
setdatalabel(data,obj) {
let that=this
//新建dataobj存储总数据,dataArr用来存储echarts的series属性的数据,处理完成的数据放在这里即可
let dataobj={
sort:obj.name, //当前标签在数组editableTabs中的位置
shapeType:"", //存储当前标签需要展示的图表类型(bar line pie )
title:obj.title, //当前标签名称(echarts的title)
dataArr:[] //存放处理完成的series数据
}
//将data包含的图表类型赋给dataobj.shapeType
// 分辨展示类型
// 根据不同的图表类型执行不同的的处理方法
if(dataobj.shapeType=="pie"){
that.setPieData(dataobj,data)
}else if(dataobj.shapeType=="line"){
that.setLineDate(dataobj,data)
}
},
第三步 创建图表数据
数据处理完成之后,将携带数据的dataobj传递给渲染图表的方法,(这里折线图和柱状图可以使用同一个方法,处理数据时动态修改type即可)
setLineDate(dataobj,data){
//处理数据的逻辑
//........
//.........
//处理完成之后创建图表
this.createlinechart(dataobj)
}
createlinechart(dataobj) {
let that = this;
let option = (option = {
title: {
text: dataobj.title,
textStyle: {
fontSize: 14,
color: "#626262",
},
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "",
},
backgroundColor: "white",
extraCssText: "box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);",
borderColor: "#ECECEC",
textStyle: {
//字体样式
color: "#979797",
align: "left",
},
confine: true,
},
legend: {
icon: dataobj.shapeType=='bar'?'':'circle',
x: "right",
y: "0%",
},
grid: {
left: "3%",
right: "4%",
bottom: "3%",
containLabel: true,
},
xAxis: [
{
type: "category",
data: this.chartXisArr, //x轴数据
axisPointer: {
type: "",
},
axisLabel: {
color: "#E1E1E1",
},
axisTick: {
show: false,
},
axisLine: {
lineStyle: {
color: "#E1E1E1",
},
},
},
],
yAxis: [
{
type: "value",
show: true,
axisLabel: {
formatter: "{value} /人次",
color: "#E1E1E1",
},
axisTick: {
//y轴刻度线
show: false,
},
axisLine: {
//y轴
show: false,
},
},
],
series: dataobj.dataArr,
});
this.$nextTick(()=>{
//对对应标签的echarts实例执行setOption()
this.editableTabs[Number(dataobj.sort)].chart.setOption(option, true);
//由于设置了动态宽高,所以需要resize()
this.editableTabs[Number(dataobj.sort)].chart.resize()
})
},
如果是饼图则执行饼图的处理数据方法并 setOption() 即可,同理如果需要其他图表类型,则继续添加对应处理方法即可。
最后附上效果图,(新手一枚,如有错误还请指正!)