1. 设计逻辑
节点展开细节
需求逐级展开,每次展开节点周围一层的节点,并且绘制出已存在节点的关系。
节点收缩细节
需求逐层收缩,每次收缩周围一层的节点,并且取消消失节点之间的关系。
为了保持思维流畅性(用户友好性),在收缩的时候采取,收缩当前节点的子节点,并且收缩上一层节点的孤立点,下一层的并不实现收缩。
代码实现
openOrFold(param) {
var option = this.myChart1.getOption();
var nodesOption = option.series[0].data;
var linksOption = option.series[0].edges;
var data = param.data;
var linksNodes = [];
if (data != null && data != undefined) {
if (data.flag) {
var tempNodes = [];
// 如果节点已经展开,将其所有的关联节点隐藏
for (let m in linksOption) {
// 找上下“已经显示的孤立的”层节点隐藏
if (
linksOption[m].target == data.id &&
nodesOption[linksOption[m].source].category >= 0 &&
!nodesOption[linksOption[m].source].flag
) {
// 找下层
// tempNodes.push(nodesOption[linksOption[m].source])
linksNodes.push(linksOption[m].source);
} else if (
linksOption[m].source == data.id &&
nodesOption[linksOption[m].target].category >= 0 &&
!nodesOption[linksOption[m].target].flag
) {
// 找上层
tempNodes.push(nodesOption[linksOption[m].target])
linksNodes.push(linksOption[m].target);
}
}
// 找孤立点
var temp = [];
for(let i in linksOption){
for(let j in tempNodes){
if(linksOption[i].target == tempNodes[j].id
&& nodesOption[linksOption[i].source].category>=0 && linksOption[i].source != data.id
){
// console.log(linksOption[i])
temp.push(linksOption[i].target)
}else if(linksOption[i].source == tempNodes[j].id
&& nodesOption[linksOption[i].target].category>=0 && linksOption[i].target != data.id
){
temp.push(linksOption[i].source)
}
}
}
var uniqueTemp = [...new Set(temp)]
var elementsSet = new Set(uniqueTemp)
linksNodes = linksNodes.filter
(item=>!elementsSet.has(item))
// 将上下层节点的隐藏设置
if (linksNodes != null && linksNodes != undefined) {
for (let k in linksNodes) {
nodesOption[linksNodes[k]].category =
nodesOption[linksNodes[k]].category * -1;
}
nodesOption[data.id].flag = false;
}
} else {
// 如果节点未展开,将其所有的关联节点打开
for (let m in linksOption) {
// 找上下“未显示的”层节点
if (
linksOption[m].target == data.id &&
nodesOption[linksOption[m].source].category < 0
) {
// 找下层
linksNodes.push(linksOption[m].source);
} else if (
linksOption[m].source == data.id &&
nodesOption[linksOption[m].target].category < 0
) {
// 找上层
linksNodes.push(linksOption[m].target);
}
}
// 将上下层节点的显示设置
if (linksNodes != null && linksNodes != undefined) {
for (let k in linksNodes) {
nodesOption[linksNodes[k]].category =
nodesOption[linksNodes[k]].category * -1;
}
nodesOption[data.id].flag = true;
}
}
// option.series[0].data = linksNodes;
this.myChart1.setOption(option);
}
},
按照这个逻辑则可以画出如下所示视频中的节点折叠和展开。
四、结果呈现
五、完整代码
一页完整的vue代码,DemoView.vue
数据来源:https://echarts.apache.org/examples/data/asset/data/webkit-dep.json
<template>
<div class="connection">
<div id="chart1" style="width: 90vw; height: 90vh"></div>
</div>
</template>
<script>
export default {
data() {
return {
myChart1: null,
webkitDep: {}
};
},
methods: {
init() {
var webkitDep = this.webkitDep;
this.myChart1 = this.$echarts.init(document.getElementById("chart1"));
var option = {
legend: {
data: ["Spine", "Switch", "Node"],
},
tooltip:{
formatter: (params) =>{
var chartData = params.data;
if(params.dataType == "node"){
var htmlContent = `
<div style='min-width: 310px;background: #fff; padding: 10px 5px;color: #999;font-weight: 900;'>
<div style='font-size: 14px;margin-bottom: 10px;'>
${"基本信息"}
</div>
<div style='font-size: 12px;line-height: 24px;'>
<div style="width: 100%;">
<span style='display: inline-block;width: 80px;text-align: right;padding-right: 10px;'>${"名称:"}</span>
<span style='display: inline-block;width: 180px;color: #000;'>${
chartData.name
}</span>
</div>
<div style="width: 100%;">
<span style='display: inline-block;width: 80px;text-align: right;padding-right: 10px;'>${"状态:"}</span>
<span style='display: inline-block;width: 10px;height: 10px;text-align: center;background: red;border-radius: 50%;'></span>
<span style='display: inline-block;width: 180px;color: #000;'>${
chartData.state
}</span>
</div>
<div style="width: 100%;">
<span style='display: inline-block;width: 80px;text-align: right;padding-right: 10px;'>${"IP地址:"}</span>
<span style='display: inline-block;width: 180px;color: #000;'>${
chartData.ip
}</span>
</div>
</div>
<div class="btn-tooltip" style='width: 100%; text-align: right;padding-right: 10px;color: #1e9fff; cursor: pointer;' onclick="chartClick">详情>></div>
</div>
`
}else if(params.dataType == "edge"){
}
return htmlContent
}
},
series: [
{
type: "graph",
layout: "force",
animation: false,
label: {
show: false ,
position: "right",
formatter: "{b}",
},
draggable: true,
roam: true,
data: webkitDep.nodes.map(function (node, idx) {
node.id = idx;
return node;
}),
categories: webkitDep.categories,
force: {
// edgeLength: [50,100],
repulsion: 500,
gravity: 0,
},
edges: webkitDep.links,
emphasis: {
focus: "adjacency",
label: {
position: "right",
show: true,
},
},
},
],
};
this.myChart1.setOption(option);
this.myChart1.on("click", this.openOrFold);
},
openOrFold(param) {
var option = this.myChart1.getOption();
var nodesOption = option.series[0].data;
var linksOption = option.series[0].edges;
var data = param.data;
var linksNodes = [];
if (data != null && data != undefined) {
if (data.flag) {
var tempNodes = [];
// 如果节点已经展开,将其所有的关联节点隐藏
for (let m in linksOption) {
// 找上下“已经显示的孤立的”层节点隐藏
if (
linksOption[m].target == data.id &&
nodesOption[linksOption[m].source].category >= 0 &&
!nodesOption[linksOption[m].source].flag
) {
// 找下层
// tempNodes.push(nodesOption[linksOption[m].source])
linksNodes.push(linksOption[m].source);
} else if (
linksOption[m].source == data.id &&
nodesOption[linksOption[m].target].category >= 0 &&
!nodesOption[linksOption[m].target].flag
) {
// 找上层
tempNodes.push(nodesOption[linksOption[m].target])
linksNodes.push(linksOption[m].target);
}
}
// 找孤立点
var temp = [];
for(let i in linksOption){
for(let j in tempNodes){
if(linksOption[i].target == tempNodes[j].id
&& nodesOption[linksOption[i].source].category>=0 && linksOption[i].source != data.id
){
// console.log(linksOption[i])
temp.push(linksOption[i].target)
}else if(linksOption[i].source == tempNodes[j].id
&& nodesOption[linksOption[i].target].category>=0 && linksOption[i].target != data.id
){
temp.push(linksOption[i].source)
}
}
}
var uniqueTemp = [...new Set(temp)]
var elementsSet = new Set(uniqueTemp)
linksNodes = linksNodes.filter
(item=>!elementsSet.has(item))
// 将上下层节点的隐藏设置
if (linksNodes != null && linksNodes != undefined) {
for (let k in linksNodes) {
nodesOption[linksNodes[k]].category =
nodesOption[linksNodes[k]].category * -1;
}
nodesOption[data.id].flag = false;
}
} else {
// 如果节点未展开,将其所有的关联节点打开
for (let m in linksOption) {
// 找上下“未显示的”层节点
if (
linksOption[m].target == data.id &&
nodesOption[linksOption[m].source].category < 0
) {
// 找下层
linksNodes.push(linksOption[m].source);
} else if (
linksOption[m].source == data.id &&
nodesOption[linksOption[m].target].category < 0
) {
// 找上层
linksNodes.push(linksOption[m].target);
}
}
// 将上下层节点的显示设置
if (linksNodes != null && linksNodes != undefined) {
for (let k in linksNodes) {
nodesOption[linksNodes[k]].category =
nodesOption[linksNodes[k]].category * -1;
}
nodesOption[data.id].flag = true;
}
}
// option.series[0].data = linksNodes;
this.myChart1.setOption(option);
}
},
},
mounted() {
this.init();
},
};
</script>
<style scoped></style>
浅笑べ安然394: 你好,有没有定理2.1及其证明过程呀?
CSDN-Ada助手: Python入门 技能树或许可以帮到你:https://edu.csdn.net/skill/python?utm_source=AI_act_python
CSDN-Ada助手: 推荐 Python入门 技能树:https://edu.csdn.net/skill/python?utm_source=AI_act_python
陋室--德馨: 要使用在容器中创建新用户,并设置密码,可通过ssh远程连接
争取多学一点: 为什么我的ssh配置文件里没有 PermitRootLogin yes这一项