vue+echarts实现依赖关系无向网络拓扑结图节点折叠展开策略

目录

引言

一、设计

1. 树状图(不方便呈现节点之间的关系,次要考虑)

2. 力引导依赖关系图

二、力引导关系图

三、如何实现节点的Open Or Fold

1. 设计逻辑

节点展开细节

节点收缩细节

代码实现

四、结果呈现

五、完整代码


引言

我考虑到如何实现关系图的缩放,但是关系图并不是简单的一个树结构,关系会存在于各个节点之间,两个同一层级之间的节点之间也会有一定的关系。

那么如何实现节点之间的折叠和展开策略,成为了这个图设计的关键要素。

一、设计

1. 树状图(不方便呈现节点之间的关系,次要考虑)

2. 力引导依赖关系图

    引力中心为图片中心(考虑到尽可能多的呈现信息,所以引力中心设置为中心)

    层级设计:重量按照由中心向四周分布,层级权重也是如此分布。

二、力引导关系图

"力引导关系图"通常指的是一种可视化方法,用于展示图形中节点之间的关系和连接。这种图形通常采用力导向布局算法,其中节点之间的吸引力和排斥力被用来模拟真实世界中的物理力,以确定节点在图中的相对位置。

  1. 节点(Nodes): 表示图中的个体、对象或数据点。每个节点通常代表一个实体,如人物、城市、概念等。

  2. 边(Edges): 表示节点之间的连接或关系。边可以是有向的或无向的,具体取决于关系的性质。

  3. 力导向布局算法: 使用物理模型来模拟节点之间的力的作用,以确定节点的位置。这些力包括吸引力(使相连接的节点靠近)和排斥力(使不相连接的节点远离)。这种算法通过模拟物理系统中的粒子之间的相互作用来达到节点布局的目的。

  4. 布局: 节点根据力导向算法的计算结果被放置在图形中的特定位置,以便更好地展示节点之间的关系。

  5. 可视化: 力引导关系图提供了一种直观的方式来理解图中节点的关系,使得那些有关联的节点更接近,而没有关联的节点相对较远。这有助于发现图中的模式、集群或其他重要信息。

这种图形在许多领域中都有应用,例如社交网络分析、生物信息学、知识图谱可视化等。

三、如何实现节点的Open Or Fold

echarts3之后的关系图节点的书写按照以下规则:

var myChart = echarts.init(document.getElementById('main'), 'macarons');            // 指定图表的配置项和数据
            var option = {
                tooltip : {
                    show : true,   //默认显示
                    showContent:true, //是否显示提示框浮层
                    trigger:'item',//触发类型,默认数据项触发
                    triggerOn:'click',//提示触发条件,mousemove鼠标移至触发,还有click点击触发
                    alwaysShowContent:false, //默认离开提示框区域隐藏,true为一直显示
                    showDelay:0,//浮层显示的延迟,单位为 ms,默认没有延迟,也不建议设置。在 triggerOn 为 'mousemove' 时有效。
                    hideDelay:200,//浮层隐藏的延迟,单位为 ms,在 alwaysShowContent 为 true 的时候无效。
                    enterable:false,//鼠标是否可进入提示框浮层中,默认为false,如需详情内交互,如添加链接,按钮,可设置为 true。
                    position:'right',//提示框浮层的位置,默认不设置时位置会跟随鼠标的位置。只在 trigger 为'item'的时候有效。
                    confine:false,//是否将 tooltip 框限制在图表的区域内。外层的 dom 被设置为 'overflow: hidden',或者移动端窄屏,导致 tooltip 超出外界被截断时,此配置比较有用。
                    transitionDuration:0.4,//提示框浮层的移动动画过渡时间,单位是 s,设置为 0 的时候会紧跟着鼠标移动。
                    formatter: function (params, ticket, callback) {
                        //判断数据,提供相应的url。
                        var path="";
                        var node=params.data; //当前选中节点数据
                        var category=params.data.category;  //选中节点图例0负载 1中间件 2端口号 3数据库 4用户名 
                        if(category==2){ //为jvm 虚拟机各类参数的路径
                            path = "${ctx}/weblogic.do?host=" + node.host + "&port="
                            + node.port + "&username=" + node.username
                            + "&pwd=" + node.pwd; //准备访问路径
                        }else if(category==4){ //为jdbc 数据库的路径
                            path = "${ctx}/oracle.do?host=" + node.host + "&port="
                            + node.port + "&username=" + node.username
                            + "&pwd=" + node.pwd + "&instance="
                            + node.instance; //准备访问路径
                        }
                        
                        console.log(params);
                        $.ajax({
                            async : true,//设置异、同步加载
                            cache : false,//false就不会从浏览器缓存中加载请求信息了
                            type : 'post',
                            dataType : "json",
                            url : path,//请求的action路径  
                            success : function(data) { //请求成功后处理函数。    
                                //加工返回后的数据
                                debugger;
                                if(category==2){ //当选择端口号时
                                    var res = 'jvm最大内存值:' + data.memoryMaxSize+'<br/>';
                                    res+='jvm空闲内存值:'+data.memoryFreeSize+'<br/>';
                                    res+='jvm内存使用率:'+data.memoryPer+'<br/>';
                                    res+='空闲线程:'+data.ideThread+'<br/>';
                                    res+='总线程:'+data.totalThread+'<br/>';
                                    res+='每秒处理的线程数比率:'+data.throuhput+'<br/>';
                                    callback(ticket,res);
                                }else if(category==4){//当选择用户名时
                                    var res = '当前链接数:'+data.processCount+'<br/>';
                                    res+='最大链接数:'+data.maxProcessCount+'<br/>';
                                    callback(ticket,res);
                                }
                                
                            },
                            error : function() {//请求失败处理函数  
                            $.messager.alert('警告', '请求失败!', 'warning');
                            }
                        });
                        if(category==2||category==4){ //当选择端口号与用户名时提示加载
                            return "loading";
                        }else{                   //其他情况显示所属图例以及名称
                            return myChart.getOption().series[params.seriesIndex].categories[params.data.category].name+":"+params.name;
                        }
                        
                    }
                },
 
                legend : { //=========圖表控件
                    show : true,
                    data : [ {
                        name : '负载',
                        
                        icon : 'rect'//'circle', 'rect', 'roundRect', 'triangle', 'diamond', 'pin', 'arrow'
            
                    },
                    {
                        name : '中间件',
                        
                        icon : 'roundRect'
                    }, {
                        name : '端口号',
                        
                        icon : 'circle'
                    }, {
                        name : '数据库',
                        
                        icon : 'circle'
                    },{
                        name : '用户名',
                        icon : 'roundRect'
                    } ]
                },
                series : [ {
                    type : 'graph', //关系图
                    name : "监控管理系统", //系列名称,用于tooltip的显示,legend 的图例筛选,在 setOption 更新数据和配置项时用于指定对应的系列。
                    layout : 'force', //图的布局,类型为力导图,'circular' 采用环形布局,见示例 Les Miserables
                    legendHoverLink : true,//是否启用图例 hover(悬停) 时的联动高亮。
                    hoverAnimation : true,//是否开启鼠标悬停节点的显示动画
                    coordinateSystem : null,//坐标系可选
                    xAxisIndex : 0, //x轴坐标 有多种坐标系轴坐标选项
                    yAxisIndex : 0, //y轴坐标 
                    force : { //力引导图基本配置
                        //initLayout: ,//力引导的初始化布局,默认使用xy轴的标点
                        repulsion : 100,//节点之间的斥力因子。支持数组表达斥力范围,值越大斥力越大。
                        gravity : 0.03,//节点受到的向中心的引力因子。该值越大节点越往中心点靠拢。
                        edgeLength :80,//边的两个节点之间的距离,这个距离也会受 repulsion。[10, 50] 。值越小则长度越长
                        layoutAnimation : true
                    //因为力引导布局会在多次迭代后才会稳定,这个参数决定是否显示布局的迭代动画,在浏览器端节点数据较多(>100)的时候不建议关闭,布局过程会造成浏览器假死。                        
                    },
                    roam : true,//是否开启鼠标缩放和平移漫游。默认不开启。如果只想要开启缩放或者平移,可以设置成 'scale' 或者 'move'。设置成 true 为都开启
                    nodeScaleRatio : 0.6,//鼠标漫游缩放时节点的相应缩放比例,当设为0时节点不随着鼠标的缩放而缩放
                    draggable : true,//节点是否可拖拽,只在使用力引导布局的时候有用。
                    focusNodeAdjacency : true,//是否在鼠标移到节点上的时候突出显示节点以及节点的边和邻接节点。
                    //symbol:'roundRect',//关系图节点标记的图形。ECharts 提供的标记类型包括 'circle'(圆形), 'rect'(矩形), 'roundRect'(圆角矩形), 'triangle'(三角形), 'diamond'(菱形), 'pin'(大头针), 'arrow'(箭头)  也可以通过 'image://url' 设置为图片,其中 url 为图片的链接。'path:// 这种方式可以任意改变颜色并且抗锯齿
                    //symbolSize:10 ,//也可以用数组分开表示宽和高,例如 [20, 10] 如果需要每个数据的图形大小不一样,可以设置为如下格式的回调函数:(value: Array|number, params: Object) => number|Array
                    //symbolRotate:,//关系图节点标记的旋转角度。注意在 markLine 中当 symbol 为 'arrow' 时会忽略 symbolRotate 强制设置为切线的角度。
                    //symbolOffset:[0,0],//关系图节点标记相对于原本位置的偏移。[0, '50%']
                    edgeSymbol : [ 'none', 'none' ],//边两端的标记类型,可以是一个数组分别指定两端,也可以是单个统一指定。默认不显示标记,常见的可以设置为箭头,如下:edgeSymbol: ['circle', 'arrow']
                    edgeSymbolSize : 10,//边两端的标记大小,可以是一个数组分别指定两端,也可以是单个统一指定。
                    itemStyle : {//===============图形样式,有 normal 和 emphasis 两个状态。normal 是图形在默认状态下的样式;emphasis 是图形在高亮状态下的样式,比如在鼠标悬浮或者图例联动高亮时。
                        normal : { //默认样式
                            label : {
                                show : true
                            },
                            borderType : 'solid', //图形描边类型,默认为实线,支持 'solid'(实线), 'dashed'(虚线), 'dotted'(点线)。
                            borderColor : 'rgba(255,215,0,0.4)', //设置图形边框为淡金色,透明度为0.4
                            borderWidth : 2, //图形的描边线宽。为 0 时无描边。
                            opacity : 1
                        // 图形透明度。支持从 0 到 1 的数字,为 0 时不绘制该图形。默认0.5
 
                        },
                        emphasis : {//高亮状态
 
                        }
                    },
                    lineStyle : { //==========关系边的公用线条样式。
                        normal : {
                            color : 'rgba(255,0,255,0.4)',
                            width : '3',
                            type : 'dotted', //线的类型 'solid'(实线)'dashed'(虚线)'dotted'(点线)
                            curveness : 0.3, //线条的曲线程度,从0到1
                            opacity : 1
                        // 图形透明度。支持从 0 到 1 的数字,为 0 时不绘制该图形。默认0.5
                        },
                        emphasis : {//高亮状态
 
                        }
                    },
                    label : { //=============图形上的文本标签
                        normal : {
                            show : true,//是否显示标签。
                            position : 'inside',//标签的位置。['50%', '50%'] [x,y]
                            textStyle : { //标签的字体样式
                                color : '#cde6c7', //字体颜色
                                fontStyle : 'normal',//文字字体的风格 'normal'标准 'italic'斜体 'oblique' 倾斜
                                fontWeight : 'bolder',//'normal'标准'bold'粗的'bolder'更粗的'lighter'更细的或100 | 200 | 300 | 400...
                                fontFamily : 'sans-serif', //文字的字体系列
                                fontSize : 12, //字体大小
                            }
                        },
                        emphasis : {//高亮状态
 
                        }
                    },
                    edgeLabel : {//==============线条的边缘标签 
                        normal : {
                            show : false
                        },
                        emphasis : {//高亮状态
 
                        }
                    },
                    //别名为nodes   name:影响图形标签显示,value:影响选中后值得显示,category:所在类目的index,symbol:类目节点标记图形,symbolSize:10图形大小
                    //label:标签样式。
                    data : [ {
                        id : 0,
                        category : 0,
                        name : '101.133.8.88',
                        symbol : 'roundRect',
                        value : 20,
                        symbolSize : 80
                    }, {
                        id : 1,
                        category : 1,
                        name : '192.168.8.88',
                        symbol : 'rect',
                        value : 20,
                        symbolSize : 70
                    }, {
                        id : 2,
                        category : 2,
                        name : '7001',
                        symbol : 'circle',
                        value : 20,
                        symbolSize : 60,
                        yId:"jvm",
                        host:"192.168.6.37",
                        port:"7001",
                        username:"weblogic",
                        pwd:"weblogic1"
                    }, {
                        id : 3,
                        category : 2,
                        name : '7100',
                        symbol : 'circle',
                        value : 20,
                        symbolSize : 60
                    }, {
                        id : 4,
                        category : 1,
                        name : '102.12.33.23',
                        symbol : 'rect',
                        value : 20,
                        symbolSize : 70
                    }, {
                        id : 5,
                        category : 2,
                        name : '7001',
                        symbol : 'circle',
                        value : 20,
                        symbolSize : 60
                    }, {
                        id : 6,
                        category : 2,
                        name : '7100',
                        symbol : 'circle',
                        value : 20,
                        symbolSize : 60
                    }, {
                        id : 7,
                        category : 2,
                        name : '7001',
                        symbol : 'circle',
                        value : 20,
                        symbolSize : 60
                    }, {
                        id : 8,
                        category : 1,
                        name : '101.11.66.6',
                        symbol : 'rect',
                        value : 20,
                        symbolSize : 70
                    }, {
                        id : 9,
                        category : 2,
                        name : '7101',
                        symbol : 'circle',
                        value : 20,
                        symbolSize : 60
                    }, {
                        id : 10,
                        category : 2,
                        name : '7101',
                        symbol : 'circle',
                        value : 20,
                        symbolSize : 60
                    }, {
                        id : 11,
                        category : 2,
                        name : '7001',
                        symbol : 'circle',
                        value : 20,
                        symbolSize : 60
                    }, {
                        id : 12,
                        category : 2,
                        name : '7100',
                        symbol : 'circle',
                        value : 20,
                        symbolSize : 60
                    }, {
                        id : 13,
                        category : 3,
                        name : '192.168.44.44',
                        symbol : 'circle',
                        value : 20,
                        symbolSize : 70
                    }, {
                        id : 14,
                        category : 3,
                        name : '192.168.33.33',
                        symbol : 'circle',
                        value : 20,
                        symbolSize : 70
                    }, {
                        id : 15,
                        category : 3,
                        name : '192.168.22.22',
                        symbol : 'circle',
                        value : 20,
                        symbolSize : 70
                    }, {
                        id : 16,
                        category : 4,
                        name : '55555555555',
                        symbol : 'circle',
                        value : 20,
                        symbolSize : 70,
                        yId:"jdbc",
                        port:"1521",
                        host:"192.168.11.11",
                        username:"222222222",
                        pwd:"11111111",
                        instance:"orcl"
                    }],
                    categories : [ //symbol name:用于和 legend 对应以及格式化 tooltip 的内容。 label有效
                    {
                        name : '负载',
                        symbol : 'rect',
                        label : { //标签样式
                        }
                    }, {
                        name : '中间件',
                        symbol : 'rect'
                    }, {
                        name : '端口号',
                        symbol : 'roundRect'
                    }, {
                        name : '数据库',
                        symbol : 'roundRect'
                    }, {
                        name : '用户名',
                        symbol : 'roundRect'
                    } ],
                    links : [ //edges是其别名代表节点间的关系数据。
                    {
                        source : 1,
                        target : 0
                    }, {
                        source : 4,
                        target : 0
                    }, {
                        source : 8,
                        target : 0
                    }, {
                        source : 2,
                        target : 1
                    }, {
                        source : 3,
                        target : 1
                    }, {
                        source : 5,
                        target : 4
                    }, {
                        source : 6,
                        target : 4
                    }, {
                        source : 7,
                        target : 4
                    }, {
                        source : 9,
                        target : 8
                    }, {
                        source : 10,
                        target : 8
                    }, {
                        source : 11,
                        target : 8
                    }, {
                        source : 12,
                        target : 8
                    }, {
                        source : 13,
                        target : 6
                    }, {
                        source : 14,
                        target : 6
                    }, {
                        source : 15,
                        target : 2
                    }, {
                        source : 16,
                        target : 15
                    } ]
                } ]
            };
 
            // 使用刚指定的配置项和数据显示图表。
            myChart.setOption(option);
            
            /*ECharts3 方法部分 开始*/
            
            function openOrFold(params) {  //该事件会提示节点间关系
               ...
            }
            //var ecConfig = echarts.config; echarts2的获取事件方法,当前为echarts3
            myChart.on('mouseover', openOrFold);
            //'click'、'dblclick'、'mousedown'、'mousemove'、'mouseup'、'mouseover'、'mouseout' 
            /*ECharts3 方法部分 结束*/
            
            /*ECharts3 结束*/

那么如何实现鼠标点击或者悬停实现节点的折叠和展开呢?

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);
      }
    },

按照这个逻辑则可以画出如下所示视频中的节点折叠和展开。

四、结果呈现

FlodOrOPen

五、完整代码

一页完整的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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/197080.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

离散数学-集合论基础

3.1集合的基本概念 1&#xff09;集合及元素 2&#xff09;集合的表示 3&#xff09;集合的关系 4&#xff09;特殊集合 3.2集合的运算 并、交、差、对称差 3.3集合的划分与覆盖 3.4排斥包含管理 3.1集合的基本概念 1&#xff09;集合及元素 将某种具有同种属性的个体…

扩散模型实战(十三):ControlNet结构以及训练过程

推荐阅读列表&#xff1a; 扩散模型实战&#xff08;一&#xff09;&#xff1a;基本原理介绍 扩散模型实战&#xff08;二&#xff09;&#xff1a;扩散模型的发展 扩散模型实战&#xff08;三&#xff09;&#xff1a;扩散模型的应用 扩散模型实战&#xff08;四&#xff…

振南技术干货集:znFAT 硬刚日本的 FATFS 历险记(9)

注解目录 1、znFAT 的起源 1.1 源于论坛 &#xff08;那是一个论坛文化兴盛的年代。网友 DIY SDMP3 播放器激起了我的兴趣。&#xff09; 1.2 硬盘 MP3 推了我一把 &#xff08;“坤哥”的硬盘 MP3 播放器&#xff0c;让我深陷 FAT 文件系统不能自拔。&#xff09; 1.3 我…

智能优化算法应用:基于缎蓝园丁鸟算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于缎蓝园丁鸟算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于缎蓝园丁鸟算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.缎蓝园丁鸟算法4.实验参数设定5.算法结果…

WIN10 x86环境部署ARM虚拟机(银河麒麟)

我们经常使用的是x86架构的cpu&#xff0c;而对于不同cpu架构的arm架构的操作系统&#xff0c;我们可以通过QEMU模拟器来进行模拟一个arm环境 1、部署前的准备 arm的镜像&#xff1a; 以此镜像为例&#xff1a;Kylin-Server-10-SP2-aarch64-Release-Build09-20210524.iso QE…

每日一练【移动零】

一、题目描述 283. 移动零 - 力扣&#xff08;LeetCode&#xff09; 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 二、题目解析 可以…

docker限制容器内存的方法

在服务器中使用 docker 时&#xff0c;如果不对 docker 的可调用内存进行限制&#xff0c;当 docker 内的程序出现不可预测的问题时&#xff0c;就很有可能因为内存爆炸导致服务器主机的瘫痪。而对 docker 进行限制后&#xff0c;可以将瘫痪范围控制在 docker 内。 因此&#…

1、nmap常用命令

文章目录 1. 主机存活探测2. 常见端口扫描、服务版本探测、服务器版本识别3. 全端口&#xff08;TCP/UDP&#xff09;扫描4. 最详细的端口扫描5. 三种TCP扫描方式&#xff08;1&#xff09;TCP connect 扫描&#xff08;2&#xff09;TCP SYN扫描&#xff08;3&#xff09;TCP …

两部手机数据传输后备忘录不见了怎么回事

想必很多人都遇到过&#xff0c;当两部手机进行备忘录数据传输后&#xff0c;突然发现备忘录不见了&#xff0c;这让人不禁着急上火&#xff0c;我也曾经遇到过这种事情导致很多重要的内容都丢失了。 一般出现这种情况可能是因为&#xff0c;两部手机使用的是不同的云服务&…

2020年3月25日 Go生态洞察:Go、Go社区与疫情大流行

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

04 # 第一个 TypeScript 程序

初始化项目以及安装依赖 新建 ts_in_action 文件夾 npm init -y安装好 typescript&#xff0c;就可以执行下面命令查看帮助信息 npm i typescript -g tsc -h创建配置文件&#xff0c;执行下面命令就会生成一个 tsconfig.json 文件 tsc --init使用 tsc 编译一个 js 文件 新…

Element-ui合并table表格列方法

merageCell({ row, column, rowIndex, columnIndex }) {if (columnIndex 0 || columnIndex 1) {const property columnIndex 0 ? name : firstDeptName;// 获取当前行的property&#xff0c;这里看自己的需要&#xff0c;改成根据哪个去判断const currentPropertyVal row…

ChatGPT到底是如何运作?

自从2022年11月30日发布以来&#xff0c;ChatGPT一直占据着科技届的头条位置&#xff0c;随着苹果的创新能力下降&#xff0c;ChatGPT不断给大家带来震撼&#xff0c;2023年11月7日&#xff0c;首届OpenAI开发者大会在洛杉矶举行&#xff0c;业界普遍认为&#xff0c;OpenAI的开…

Text-to-SQL小白入门(九)InstructGPT论文:教你如何训练ChatGPT

论文概述 InstructGPT和ChatGPT 的训练流程基本一致 &#xff0c;ChatGPT是改进后的InstructGPT&#xff0c;比如InstructGPT是基于GPT-3训练&#xff0c;而ChatGPT是基于GPT-3.5训练。 基本信息 英文标题&#xff1a;Training language models to follow instructions with h…

香港科技大学广州|智能制造学域博士招生宣讲会—华中科技大学专场

时间&#xff1a;2023年12月08日&#xff08;星期五&#xff09;15:00 地点&#xff1a;华中科技大学大学生活动中心A座603 报名链接&#xff1a;https://www.wjx.top/vm/mmukLPC.aspx# 宣讲嘉宾&#xff1a; 胡鹏程 副教授 https://facultyprofiles.hkust-gz.edu.cn/faculty-…

RabbitMQ消息队列

简介 MQ(message queue)&#xff0c;从字面意思上看就个 FIFO 先入先出的队列&#xff0c;只不过队列中存放的内容是 message 而已&#xff0c;它是一种具有接收数据、存储数据、发送数据等功能的技术服务。 作用&#xff1a;流量削峰、应用解耦、异步处理。 生产者将消息发送…

黑马点评-Feed流的实现方案,基于推拉结合模式实现笔记推送

Feed流实现方案 我们关注了博主之后,当用户发布了动态后我们应该把这些数据推送给粉丝,关注推送也叫作Feed(投喂)流,通过无限下拉刷新获取新的信息 传统的模式内容检索: 粉丝需要主动通过搜索引擎或者是其他方式去查找想看的内容新型Feed流的效果: 系统分析用户到底想看什么,…

okhttp系列-拦截器的执行顺序

1.将拦截器添加到ArrayList final class RealCall implements Call {Response getResponseWithInterceptorChain() throws IOException {//将Interceptor添加到ArrayListList<Interceptor> interceptors new ArrayList<>();interceptors.addAll(client.intercept…

注意力机制(Attention Mechanism)

目录 1. 简介&#xff1a;探索注意力机制的世界 2. 历史背景 3. 核心原理 4. 应用案例 5. 技术挑战与未来趋势 6. 图表和示例 7. Conclusion 1. 简介&#xff1a;探索注意力机制的世界 在当今的人工智能&#xff08;AI&#xff09;和机器学习&#xff08;ML&#xff09;…

戴尔科技推出全新96核Precision 7875塔式工作站

工作站行业一直是快节奏且充满惊喜的。在过去25年中,戴尔Precision一直处于行业前沿,帮助创作者、工程师、建筑师、研究人员等将想法变为现实,并对整个世界产生影响。工作站所发挥的作用至关重要,被视为化不可能为可能的必要工具。如今,人工智能(AI)和生成式AI(GenAI)的浪潮正在…