需求:走马灯中按照任务区分,每个任务可能存在多个类别(第一层循环);每个任务类别会展示详情和多个子任务(第二层循环)。
HTML布局
由于使用v-for渲染多个图表,基本html结构如下[1]:
<el-carousel-item v-for="(taskItemList, index) in taskInfoList" :key="index">
<div class="content-wrapper">
<div class="content-info" v-for="(item, itemIndex) in taskItemList" :key="itemIndex">
<div class="content-item">
<span class="item-info">任务:{{item.name}}</span>
<span class="item-info">类别:{{ item.typeName }}</span>
<span class="item-info">启动测试时间:{{ item.startTime}}</span>
<span class="item-info">预期完成时间:{{ item.targetTime }}</span>
<span class="item-info">当前整体进度:{{ item.progress }}</span>
<span class="item-info">当前激活bug:{{ item.bugCount }}</span>
<span class="item-info">执行人:{{item.pmName}}</span>
<span class="item-info">开发:{{ item.devName }}</span>
</div>
<div class="pieChart" :data-index=index :data-itemIndex=itemIndex :style="{width: '800px', height: '300px', marginLeft: '40px', zoom: chartsZoom}"></div>
</div>
</div>
</el-carousel-item>
</el-carousel>
多图表处理的问题细节
由于需要处理多个echarts实例,处理中需要注意一些细节问题:
- 使用getElementsByClassName("pieChart")获取HTMLCollection集合,并循环遍历其中的元素对象初始化Echarts实例;
- 遍历任务的数据中(taskInfoList)子任务数据需要任务索引carouselIndex 和子任务索引itemIndex,才可以和实例对应上,data-* 属性来将数据的索引传入对应的饼图。
initPieCharts() {
let myCharts = document.getElementsByClassName("pieChart");
for(let i = 0;i < myCharts.length ; i++) {
let myChart = echarts.init(myCharts[i]);
let carouselIndex = myCharts[i].getAttribute('data-index'); // 传入轮播看板的索引
let itemIndex = myCharts[i].getAttribute('data-itemIndex'); // 传入轮播看板中子任务的索引
var option;
option = {
tooltip: {
trigger: 'item'
},
legend: {
top: '5%',
orient: 'vertical', // 纵向排布
left: 'left', // legend位置
textStyle:{
fontSize: 16,
color: "#fff"
},
lineStyle: {
width: 1
},
},
series: [
{
name: 'Access From',
type: 'pie',
radius: ['50%', '70%'],
avoidLabelOverlap: false,
itemStyle: {
// borderRadius: 10, // 圆角环形图的圆角
// borderColor: '#fff',
borderWidth: 2
},
label: {
show: false,
position: 'center',
color: '#fff',
},
emphasis: {
label: {
show: true,
fontSize: 40,
fontWeight: 'bold'
}
},
labelLine: {
show: false
},
data: this.taskInfoList[carouselIndex][itemIndex].subTasks // 绑定子元素
}
]
};
option && myChart.setOption(option);
}
}
- 上述initPieCharts()中通过getElementsByClassName()获取DOM,如果在mounted()中直接调用initPieCharts()进行DOM操作,会发现HTMLCollection为空,饼图无法绘制出来。这应该是由于异步加载数据或组件嵌套较深(尝试了下mounted中getElementsByClassName只能获取到el-carousel组件的最外层),导致尝试获取DOM时组件还未完全渲染或子组件未加载完成,进而返回空数组,可使用$nextTick()确保组件渲染完成后再获取DOM。
this.$nextTick().then(() => {
this.initPieCharts()
})
- 开发过程中发现环形图悬停显示详情,会出现错位,最终定位是由于为使用不同屏幕大小使用zoom控制缩放比例。此处,使用zoom属性并将值设置为chartsZoom(chartsZoom = 1 / zoom )解决错位问题。[2]
- 饼图的视觉指示线设置,直接用labelLine并不生效。最终通过label中使用normal并设置show: true才显示出来;同时可使用formatter和rich自定义视觉指示线和label的内容样式。[3]
[1] 在Vue 中实现循环渲染多个相同echarts图表 在Vue 中实现循环渲染多个相同echarts图表_vue.js_脚本之家
[2] echarts图表悬停时错位的原因以及解决方案 [echarts]echarts图表悬停时错位的原因以及解决方案_vue 低分辨率下echarts点击错位问题-CSDN博客
[3] Echarts 系列之饼图的相关配置 https://www.cnblogs.com/yy136/p/12844443.html