Vue+G6搭建力导向图

1 效果

在这里插入图片描述
初始化时节点向中间聚拢
拖动后,随引力作用缓缓向中间聚拢
点击节点,节点放大,并展示标签文字

2 代码分析

2.1 数据

2.1.1 节点数据

nodes: [
          {
    
    
            id: '0',
            label: '0',
            value: 10,
            cluster: 'a',
            description: 'this is node 0, \nand the value of it is 10',
          },
          {
    
    
            id: '1',
            label: '1',
            value: 20,
            cluster: 'b',
            description: 'this is node 1, \nand the value of it is 20',
          },

value: 决定节点大小
cluster: a b c d 对应不同的样式 cluster值决定拿到colors、strokes数组中的某一项
label: 默认节点文本(默认配置项属性)
description: 点击节点放大后 该该数据赋值给label 展示文本

2.1.2 节点样式

样式并不是按照顺序固定给某节点的的,而是通过cluster拿到对应数组的某一项,赋予节点

	  // 节点填充颜色
      const colors = [
        '#BDD2FD',
        '#BDEFDB',
        '#C2C8D5',
        '#FBE5A2',
        '#F6C3B7',
        '#B6E3F5',
        '#D3C6EA',
        '#FFD8B8',
        '#AAD8D8',
        '#FFD6E7',
      ];
      // 节点边颜色
      const strokes = [
        '#5B8FF9',
        '#5AD8A6',
        '#5D7092',
        '#F6BD16',
        '#E8684A',
        '#6DC8EC',
        '#9270CA',
        '#FF9D4D',
        '#269A99',
        '#FF99C3',
      ];

2.2 图配置

Graph 的初始化通过 new 进行实例化,实例化时需要传入需要的参数。

<div id="container"></div>

const graph = new G6.Graph({
    
    
        container: 'container',
        width,
        height,
        layout: {
    
    
          type: 'force', // 力导向布局
          nodeStrength: 30, // 节点作用力,正数代表节点之间的引力作用,负数代表节点之间的斥力作用
          collideStrength: 0.7, // 防止重叠的力强度,范围 [0, 1]
          alphaDecay: 0.01, // 迭代阈值的衰减率 ?啥玩意
          preventOverlap: true, // 是否防止重叠 必须在数据中设置了 size 或在该布局中配置了与当前图节点大小相同的 nodeSize 值
        },
        modes: {
    
    
          default: ['collapse-expand-combo'], // combo类型 之前采用drag-node 不太丝滑
        },
        defaultNode: {
    
    
          size: [10, 10],
        },
      });

2.3 定义节点样式

// 遍历nodes 根据cluster属性 给节点添加对应style属性
      nodes.forEach((node) => {
    
    
        nodeMap.set(node.id, node);
        // cluster
        if (node.cluster && clusterMap.get(node.cluster) === undefined) {
    
    
          clusterMap.set(node.cluster, clusterId);
          clusterId++;
        }
        const cid = clusterMap.get(node.cluster);
        if (!node.style) node.style = {
    
    };
        node.style.fill = colors[cid % colors.length]; //节点颜色
        node.style.stroke = strokes[cid % strokes.length]; //节点边颜色
        node.x = width / 2 + 200 * (Math.random() - 0.5);
        node.y = height / 2 + 200 * (Math.random() - 0.5);
      });

2.4 节点大小设置

// 调用scaleNodeProp
scaleNodeProp(nodes, 'size', 'value', nodeSizeDataRange, nodeSizeRange);

      // 添加size属性
      function scaleNodeProp (elements, propName, refPropName, dataRange, outRange) {
    
    
        const outLength = outRange[1] - outRange[0];
        const dataLength = dataRange[1] - dataRange[0];
        elements.forEach(function (n) {
    
    
          if (propName.split('.')[0] === 'style') {
    
    
            if (n.style) {
    
    
              n.style[propName.split('.')[1]] =
                ((n[refPropName] - dataRange[0]) * outLength) / dataLength + outRange[0];
            } else {
    
    
              n.style = _defineProperty(
                {
    
    },
                propName.split('.')[1],
                ((n[refPropName] - dataRange[0]) * outLength) / dataLength + outRange[0],
              );
            }
          } else {
    
    
            n[propName] = ((n[refPropName] - dataRange[0]) * outLength) / dataLength + outRange[0];
          }
        });
      }

2.5 节点交互事件

  // 方法:跟随拖动的位置 节点位置移动
  // 参数e:鼠标拖动信息
  function refreshDragedNodePosition (e) {
    
    
    const model = e.item.get('model');
    model.fx = e.x;
    model.fy = e.y;
  }

2.5.1 节点开始被拖拽

  // 事件绑定 graph.on()
  // Node 交互事件: node:dragstart 当节点开始被拖拽的时候触发的事件
  graph.on('node:dragstart', function (e) {
    
    
    graph.layout(); // graph.layout()重新以当前配置的属性进行一次布局
    refreshDragedNodePosition(e);
  });

2.5.2 开始拖拽过程

  // node:drag  当节点在拖动过程中时触发的事件
  graph.on('node:drag', function (e) {
    
    
    refreshDragedNodePosition(e);
  });

2.5.3 拖拽完成后

  // node:dragend 当拖拽完成后触发的事件
  graph.on('node:dragend', function (e) {
    
    
    e.item.get('model').fx = null;
    e.item.get('model').fy = null;
  });

2.5.4 点击事件

  // node:click 鼠标左键单击节点时触发
  graph.on('node:click', function (e) {
    
    
    // debugger;
    const node = e.item; //那到当前点击的节点
    const states = node.getStates(); //返回当前元素的所有状态 啥也没有
    let clicked = false;
    const model = node.getModel(); // 获得节点位置
    let size = 200; // 变大
    let labelText = 'NODE: ' + model.id + '\n' + model.description; // 拼接: "NODE:  this is node 8, and the value of it is 21"
    states.forEach(function (state) {
    
    
      if (state === 'click') {
    
    
        clicked = true;
        size = model.oriSize;
        labelText = model.oriLabel;
      }
    });
    graph.setItemState(node, 'click', !clicked); //设置元素状态(元素实例,状态值,是否启用状态)
    // 更新元素,包括更新数据、样式等
    graph.updateItem(node, {
    
    
      size,
      label: labelText,
    });
    graph.layout(); // graph.layout()重新以当前配置的属性进行一次布局
  });

2.6 初始化图数据

  graph.data(data); // 初始化图数据,data是一个包括 节点 数组和 边 数组的对象
  graph.render();

2.7 mounted() 调用

上述代码包裹在 getInit() 方法中
在组件挂载后调用 getInit()

猜你喜欢

转载自blog.csdn.net/weixin_52268321/article/details/131460597