1.遇到的问题 鼠标滚动时,树状图会立刻回到原始状态,未保留用户展开收起节点的操作后的状态。
解决历程:
1、经查阅文档 getOption()获取的是第一次渲染后的静态配置项目。因此在监听mousewheel事件时,动态改变字体的大小的时候,会重新渲染树结构。
2、不改变其他配置项,只改变字体大小
myChart.setOption({
series: [
{
label: {
fontSize: newFontSize,
},
},
],
});
依然会重新渲染回到最初状态。
3、手动给原数据每个对象塞collapsed 的值,监听点击事件,动态修改collapsed 的值然后重新setOption,保证用户每次操作都被记录下来。(其中想用expand事件来着,但是无效(vue3版本3.3.9 echart版本5.4.3))
以下是代码
<template>
<div class="p-16px">
<el-card class="bg-white overflow: hidden; mb-16px" style="width: 100%">
<div>
<SearchForm @search="search" :initForm="initForm" :initKv="initKv" />
</div>
</el-card>
<div style="width: 100%; height: 1000px; overflow: hidden">
<Chart
style="width: 100%; height: 1000px; overflow: hidden"
:option="chartOption"
ref="chartTreeRef"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import * as AnaApi from "@/api/statisticalAnalysis";
import SearchForm from "./SearchForm.vue";
const chartTreeRef = ref();
//写一个方法 给data的所有childern里面的对象添加flag属性,用来控制是否展开
function addCollapsed(data2) {
data2.forEach((item) => {
item.collapsed = false;
if (item.children) {
addCollapsed(item.children);
}
});
return data2;
}
function addCollapsedAll(data2, falg = 1) {
data2.forEach((item) => {
if (falg < 3) {
item.collapsed = false;
} else {
item.collapsed = true;
}
if (item.children) {
addCollapsedAll(item.children, falg + 1);
}
});
return data2;
}
function drawCloud({ data }) {
let option = {
tooltip: {
trigger: "item",
triggerOn: "mousemove",
},
grid: {
bottom: "0%",
},
animation: true,
animationThreshold: 200000,
series: [
{
type: "tree",
// expandLevel: 4, // 设置默认展示两级
data: [data],
top: "1%",
left: "7%",
bottom: "1%",
right: "20%",
symbolSize: 7,
tooltip: {
// 自定义 tooltip 的显示内容
formatter: function (x) {
if (x.data.chance != undefined) {
return x.name + "<br/>" + "概率:" + x.data.chance + "%"; //设置提示框的内容和格式 节点和边都显示name属性
} else {
return x.name;
}
},
},
label: {
position: "left",
verticalAlign: "middle",
align: "right",
fontSize: 9,
formatter: function (x) {
if (x.name.length > 15) {
return x.name.substring(0, 15) + "...";
} else {
return x.name;
}
},
},
leaves: {
label: {
position: "right",
verticalAlign: "middle",
align: "left",
},
},
emphasis: {
focus: "descendant",
},
expandAndCollapse: true,
expandLevel: 6,
roam: true,
animationDuration: 550,
animationDurationUpdate: 750,
},
],
};
return option;
}
let chartOption = ref<any>({});
const getChartData = async (params) => {
let res = await AnaApi.getFaultTreeData({
...params,
// process: "切卷",
// equipType: "切卷一体机",
});
if (params.position) {
let ddd = JSON.parse(JSON.stringify(res));
res = addCollapsed(ddd);
} else {
let ddd = JSON.parse(JSON.stringify(res));
res = addCollapsedAll(ddd);
}
chartOption.value = drawCloud({
data: res[0],
});
};
const initKv = ref({
processList: [],
equipmentTypeList: [],
childProcessList: [],
firstLevelPositionList: [],
}) as any;
const initForm = ref({
process: "",
equipmentType: "",
childProcess: "",
firstLevelPosition: "",
}) as any;
const search = async (searchParams?: any) => {
console.log("search==searchParams", searchParams);
if (searchParams && searchParams.process && searchParams.equipmentType) {
getChartData({
...searchParams,
firstLevelComponent: searchParams.firstLevelPosition,
position: searchParams.childProcess,
equipType: searchParams.equipmentType,
});
}
};
const InitForm = async () => {
// try {
// 获取所有kv的process、equipment、childProcess、firstLevelPosition
const processList = await AnaApi.processKv({});
const equipmentTypeList = await AnaApi.equipmentTypeKv({
process: processList[0].value,
});
const equipmentList = await AnaApi.equipmentKv({
process: processList[0].value,
equipmentType: equipmentTypeList[0].value,
});
const childProcessList = await AnaApi.childProcessKv({
process: processList[0].value,
equipment: equipmentList[0].value,
equipmentType: equipmentTypeList[0].value,
});
const firstLevelPositionList = await AnaApi.firstLevelPositionKv({
process: processList[0].value,
equipment: equipmentList[0].value,
equipmentType: equipmentTypeList[0].value,
childProcess: childProcessList[0].value,
});
initForm.value = {
process: processList[0].value,
equipmentType: equipmentTypeList[0].value,
childProcess: childProcessList[0].value,
firstLevelPosition: firstLevelPositionList[0].value,
};
initKv.value = {
processList,
equipmentTypeList,
childProcessList,
firstLevelPositionList,
};
// } catch (error) {
// console.log("InitForm==error");
// }
};
InitForm();
function findAndToggleCollapsed(optionData, params) {
if (!optionData || !params || !params.name) {
return null;
}
// name 一定是个唯一值,可以换成其他变量,但是一定要是唯一值,如果不是唯一值会出现,点击第二个名字,展开第一个名字的情况
if (optionData.name === params.name) {
optionData.collapsed = !optionData.collapsed;
return optionData;
}
if (optionData.children && optionData.children.length > 0) {
for (let i = 0; i < optionData.children.length; i++) {
const foundNode = findAndToggleCollapsed(optionData.children[i], params);
if (foundNode) {
return foundNode;
}
}
}
return null;
}
onMounted(() => {
chartTreeRef.value.myChart.on("click", (params) => {
let optionData = chartTreeRef.value.myChart.getOption().series[0].data; // 获取当前option
const res = findAndToggleCollapsed(optionData[0], params.data);
// 更新图表选项
chartTreeRef.value.myChart.setOption({
series: [
{
data: optionData,
},
],
});
});
chartTreeRef.value.myChart.getZr().on("mousewheel", () => {
let currentOption = chartTreeRef.value.myChart.getOption();
if (currentOption.series[0]) {
let zoom = currentOption.series[0].zoom;
const newFontSize = 9 * zoom;
chartTreeRef.value.myChart.setOption({
series: [
{
label: {
fontSize: newFontSize,
},
},
],
});
}
});
});
</script>