echarts关系图graph绘制拓扑图, 使用过程中遇到的坑...

1,339 阅读3分钟

用echarts绘制topo图,研究了下最终决定使用其中的graph关系图,由于项目中数据比较复杂,在数据处理和使用echarts绘制时,遇到了几个坑, 因此决定在此记录一下下...

一、项目情况

1.框架angular8
2.ng-zorro7.5x
3.echarts4.2.1~

二、需求

1.需求:使用echarts绘制设备间的拓扑图
选择示例:echarts 关系图graph悲惨世界人物关系图/力引导布局

三、基础代码片段

var chartDom = document.getElementById('main');
var myChart = echarts.init(chartDom, 'dark');
var option;
option = {
    title: {
      text: 'Les Miserables',
      subtext: 'Default layout',
      top: 'bottom',
      left: 'right'
    },
    tooltip: {},
    series: [
          {
            name: 'Les Miserables',
            type: 'graph',
            layout: 'force',
            data: graph.nodes,
            links: graph.links,
            categories: graph.categories,
          }
    ]
  };
  
   myChart.setOption(option);

四、数据构造

var graph = {
    "nodes": [
      {
        "id": "0",
        "name": "Myriel",
        "draggable": true
      },
      {
        "id": "1",
        "name": "Napoleon",
        "draggable": true
      },
      {
        "id": "2",
        "name": "MlleBaptistine",
        "draggable": true
      },
      {
        "id": "3",
        "name": "MmeMagloire",
        "draggable": true
      },
      {
        "id": "4",
        "name": "CountessDeLo",
        "draggable": true
      },
    ],
   "links": [
      {
        "source": "1",
        "target": "0",
        "relation": {name: 'http'},
      },
      {
        "source": "2",
        "target": "3",
        "relation": {name: 'modbus'}
      },
      {
        "source": "3",
        "target": "0",
        "relation": {name: 'mqtt'}
      },
      {
        "source": "3",
        "target": "2",
         "relation": {name: 'snmp'}
      }
    ],
    "categories": [
      {
        "name": "http",
         "itemStyle":{color:'#91e8e1'},
      },
      {
        "name": "modbus",
         "itemStyle":{color:'#2b908f'},
        
      },
      {
        "name": "mqtt",
         "itemStyle":{color:'#e4d354'},
      },
      {
        "name": "snmp",
         "itemStyle":{color:'#f15c80'},
      }
    ]
  };

五、结果如图所示

image.png

此时展示的图形们有几个问题,第一节点过小,第二不知道这些节点分别是谁,因此首先要增加节点样式

5.1 设置节点样式

节点样式可以在nodes数据中分别设置,也可以在series中直接设置,本文采用在series中统一设置的形式:

series: [
          {
            name: 'Les Miserables',
            type: 'graph',
            layout: 'force',
            data: graph.nodes,
            links: graph.links,
            categories: graph.categories,
            label: { //节点显示名称
              show: true,
              position: "bottom",
              distance: 5,
              fontSize: 18,
              align: "center",
              
            },
            // symbol: 'image:///assets/images/devices/device.png', // 设置节点图片或形状,
//circle,'rect'等,具体见官网api示例

            symbolSize: 30, // 节点大小
          }
    ]

image.png

5.2 配置series

此时我们看图可以看到,所有的节点都挨着,所以说明节点间没有排斥力,同时关系间的线的长度都没有设置,节点之间的关系也没有显示,因此直接在series增加相应的设置即可,最终的series如下:

 series: [
      {
        name: 'Les Miserables',
        type: 'graph',
        layout: 'force',
        data: graph.nodes,
        links: graph.links,
        categories: graph.categories,
        label: {
              show: true,
              position: "bottom",
              distance: 5,
              fontSize: 18,
              align: "center",
              
            },
        symbolSize: 30,
        roam: true,
        edgeSymbol: ["circle", "arrow"],
        force: { // 节点排斥力设置
            repulsion: 200,
            gravity: 0.01,
            edgeLength: 200
        },
        lineStyle: { 
          color: 'source',
          curveness: 0.3 // 线的曲率
        },
        emphasis: { //高亮状态的图形样式,v5.0版本及以上
          focus: 'adjacency',
          lineStyle: {
            width: 10
          }
        },
        edgeLabel: {//边的设置(节点之间的关系)
              show: true,
              position: "middle",
              fontSize: 12,
              formatter: (params) => {
                return params.data.relation.name;
          },
        },
      }
    ]

image.png

5.3 配置legend

此时我们可以看到图形中是没有小标题legend的,需在option中设置,最终的option如下:

option = {
    title: {
      text: 'Les Miserables',
      subtext: 'Default layout',
      top: 'bottom',
      left: 'right'
    },
    tooltip: {},
    legend: [
      {
        // selectedMode: 'single',
        data: graph.categories.map(function (a) {
          return a.name;
        })
      }
    ],
    animationDuration: 1500,
    animationEasingUpdate: 'quinticInOut',
    series:[...] // 如上已展示,在此不再具体写出
  };

image.png

5.4 legend默认点击事件不生效问题

此时可以看出legend与图形节点之间并没有一一对应,legend的默认点击不显示事件也并未生效,观察官网示例数据发现,nodes数据每条需要一个category值与categories的索引值对应。 nodes数据更改如下:

"nodes": [
      {
        "id": "0",
        "name": "Myriel",
        "draggable": true,
        "category":0
      },
      {
        "id": "1",
        "name": "Napoleon",
        "draggable": true,
        "category": 1
      },
      {
        "id": "2",
        "name": "MlleBaptistine",
         "draggable": true,
        "category": 2
      },
      {
        "id": "3",
        "name": "MmeMagloire",
        "draggable": true,
        "category": 3
      },
      {
        "id": "4",
        "name": "CountessDeLo",
        "draggable": true,
        "category": 4
      }
    ],

image.png

5.5 legend与节点间的一一对应处理

设置好nodes里的每一条category值之后,观察图片,会发现,我们有一个节点消失了,nodes有5条数据,而图中只显示了4个节点,这是为什么呢???
观察nodes的category值与categories数组发现,categories数组有四组数据,而nodes有5组数据,当ndoes的category值按照索引设置后,最大为4,此时无法与categories数组对应,因此一条数据就无法显示了,更改nodes索引值与categories一一对应就可以完美解决此问题啦,nodes最终数据为:

"nodes": [
      {
        "id": "0",
        "name": "Myriel",
        "draggable": true,
        "category":0
      },
      {
        "id": "1",
        "name": "Napoleon",
        "draggable": true,
        "category": 1
      },
      {
        "id": "2",
        "name": "MlleBaptistine",
         "draggable": true,
        "category": 2
      },
      {
        "id": "3",
        "name": "MmeMagloire",
        "draggable": true,
        "category": 3
      },
      {
        "id": "4",
        "name": "CountessDeLo",
        "draggable": true,
        "category": 3
      }
    ],

image.png

最后附echarts官网示例链接 ,以供参考:
echarts.apache.org/examples/zh…