vue中使用antvG6画分组结构图及树形关系图

效果图:

 

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

 我是对G6中提供的该图的相关函数进行了封装--下面的代码是写在公共js文件里面:


export function renderMap(data,graph){
      const collapseIcon = (x, y, r) => {
        return [
          ['M', x - r, y],
          ['a', r, r, 0, 1, 0, r * 2, 0],
          ['a', r, r, 0, 1, 0, -r * 2, 0],
          ['M', x - r + 4, y],
          ['L', x - r + 2 * r - 4, y],
        ];
      };
      const expandIcon = (x, y, r) => {
        return [
          ['M', x - r, y],
          ['a', r, r, 0, 1, 0, r * 2, 0],
          ['a', r, r, 0, 1, 0, -r * 2, 0],
          ['M', x - r + 4, y],
          ['L', x - r + 2 * r - 4, y],
          ['M', x - r + r, y - r + 4],
          ['L', x, y + r - 4],
        ];
      };

      G6.registerCombo('cRect', {
        drawShape: function drawShape(cfg, group) {
          const self = this;
          // Get the padding from the configuration
          cfg.padding = cfg.padding || [50, 20, 20, 20];
          // Get the shape's style, where the style.width and style.height correspond to the width and height in the figure of Illustration of Built-in Rect Combo
          const style = self.getShapeStyle(cfg);
          // Add a rect shape as the keyShape which is the same as the extended rect Combo
          const rect = group.addShape('rect', {
            attrs: {
              ...style,
              x: -style.width / 2 - (cfg.padding[3] - cfg.padding[1]) / 2,
              y: -style.height / 2 - (cfg.padding[0] - cfg.padding[2]) / 2,
              width: style.width,
              height: style.height
            },
            draggable: true,
            name: 'combo-keyShape'
          });
          // Add the circle on the right
          group.addShape('marker', {
            attrs: {
              ...style,
              fill: '#fff',
              opacity: 1,
              // cfg.style.width and cfg.style.heigth correspond to the innerWidth and innerHeight in the figure of Illustration of Built-in Rect Combo
              x: cfg.style.width / 2 + cfg.padding[1],
              y: (cfg.padding[2] - cfg.padding[0]) / 2,
              r: 10,
              symbol: collapseIcon
            },
            draggable: true,
            name: 'combo-marker-shape'
          });
          return rect;
        },
        // Define the updating logic of the right circle
        afterUpdate: function afterUpdate(cfg, combo) {
          const group = combo.get('group');
          // Find the circle shape in the graphics group of the Combo by name
          const marker = group.find(ele => ele.get('name') === 'combo-marker-shape');
          // Update the position of the right circle
          marker.attr({
            // cfg.style.width and cfg.style.heigth correspond to the innerWidth and innerHeight in the figure of Illustration of Built-in Rect Combo
            x: cfg.style.width / 2 + cfg.padding[1],
            y: (cfg.padding[2] - cfg.padding[0]) / 2,
            // The property 'collapsed' in the combo data represents the collapsing state of the Combo
            // Update the symbol according to 'collapsed'
            symbol: cfg.collapsed ? expandIcon : collapseIcon
          });
        }
      }, 'rect');

      G6.registerEdge(
        'line-arrow', 
        {
          getPath(points) {
            const startPoint = points[0];
            const endPoint = points[1];
            return [
              ['M', startPoint.x, startPoint.y],
              ['L', endPoint.x / 3 + (2 / 3) * startPoint.x, startPoint.y],
              ['L', endPoint.x / 3 + (2 / 3) * startPoint.x, endPoint.y],
              ['L', endPoint.x, endPoint.y],
            ];
          },
          getShapeStyle(cfg) {
            const startPoint = cfg.startPoint;
            const endPoint = cfg.endPoint;
            const controlPoints = this.getControlPoints(cfg);
            let points = [startPoint]; // the start point
            // the control points
            if (controlPoints) {
              points = points.concat(controlPoints);
            }
            // the end point
            points.push(endPoint);
            const path = this.getPath(points);
            const style = Object.assign(
              {},
              G6.Global.defaultEdge.style,
              {
                stroke: '#BBB',
                lineWidth: 1,
                path,
              },
              cfg.style,
            );
            return style;
          },
        },
        'line',
      );

      const width = document.getElementById('container').scrollWidth;
      const height = (document.getElementById('container').scrollHeight || 500) - 20;
      
      graph.data(data);
      graph.render();

      // collapse/expand when click the marker
      graph.on('combo:click', e => {
        if (e.target.get('name') === 'combo-marker-shape') {
          // graph.collapseExpandCombo(e.item.getModel().id);
          graph.collapseExpandCombo(e.item);
          if (graph.get('layout')) graph.layout();
          else graph.refreshPositions();
        }
      });

      graph.on('combo:dragend', e => {
        graph.getCombos().forEach(combo => {
          graph.setItemState(combo, 'dragenter', false);
        })
      });
      graph.on('node:dragend', e => {
        graph.getCombos().forEach(combo => {
          graph.setItemState(combo, 'dragenter', false);
        })
      });

      graph.on('combo:dragenter', e => {
        graph.setItemState(e.item, 'dragenter', true);
      });
      graph.on('combo:dragleave', e => {
        graph.setItemState(e.item, 'dragenter', false);
      });
}

然后在你需要引入该图的vue文件中引入该函数及数据:

import {renderMap} from '../../../assets/common/http' //引入刚才封装的函数

 data(){
    return{
      data_map:{  //定义一个数组就是这组图中需要传入的数据,包含节点、分组及边的信息
        nodes: [
          { id: 'node2', x: 300, y: 200,label:'i系统', comboId: 'combo2' },
          { id: 'node4', x: 300, y: 300,label:'i系统', comboId: 'combo4' },
          { id: 'node5', x: 300, y: 400,label:'i系统', comboId: 'combo4' },

          { id: 'node3', x: 100, y: 200,label:'数据工厂系统', comboId: 'combo3' },
          { id: 'node1', x: 500, y: 200,label:'数据工厂系统', comboId: 'combo1' },

        ],
        combos: [
          { id: 'combo2', label: 'Combo 2'},
          { id: 'combo3', label: 'Combo 3' },
          { id: 'combo1', label: 'Combo 1'},
          { id: 'combo4', label: 'Combo 4' ,parentId: 'combo2'},
        ],
        edges: [
          {
            source: 'node3',
            target: 'node5',
            
          },
        ],
      },
      graph:{}, //定义一个全局graph
    }
  },
  methods:{
    changeMapModel(e){  //这个函数大家可以不用看,他是用来按钮触发刷新的时候调用的函数
      setTimeout( ()=>{ //此处注意需要写延时器渲染函数,不然会出现dom元素未找到的错误
        this.graph.read(this.data_map1) //刷新图的时候只需要渲染里面的数据即可,因此调用graph                
                                    中自带的read方法去刷新
      },100)
    }
  },
  mounted(){
    this.graph = new G6.Graph({
        container: 'container',
        width:1000,
        height:500,
        groupByTypes: false,
        defaultCombo: {
          type: 'cRect',
        },
        comboStateStyles: {
          dragenter: {
            lineWidth: 4,
            stroke: '#FE9797'
          }
        },
        defaultEdge: {
          type: 'line-arrow',
          style: {
            stroke: '#F6BD16',
            endArrow: {
              path: 'M 0,0 L 12,6 L 9,0 L 12,-6 Z',
              fill: '#F6BD16',
            },
          },
        },
        defaultNode: {
          type: 'rect',
          size: [110,40],
          style: {
            fill: '#9EC9FF',
            stroke: '#5B8FF9',
            lineWidth: 3,
          },
          labelCfg: {
            style: {
              fill: '#fff',
              fontSize: 14,
            },
          },
          linkPoints: {
            left: true,
            right: true,
            size: 10,
            fill: '#fff',
            lineWidth: 1,
            stroke: '#1890FF',
          },
        },
        modes: {
          default: [
            'drag-combo',
            'drag-node',
            'drag-canvas'
          ]
        }
    })
    renderMap(this.data_map,this.graph) //所有参数准备好之后,调用刚才封装的渲染函数去渲染组件
  },

还有附上我在angualr中也是用的antvG6画的树形关系图,跟vue里面的原理一样,可以参考一下:

https://blog.csdn.net/qq_41579104/article/details/105861713

效果是这样:

还有一种是节点可增删改的树形结构图,vue写的,可参考一下:

https://blog.csdn.net/qq_41579104/article/details/113388616

效果是这样:

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
1. 安装antvG6 ```bash npm install @antv/g6 --save ``` 2. 在Vue组件引入antvG6 ```vue <template> <div id="container"></div> </template> <script> import G6 from '@antv/g6'; export default { name: 'CustomLine', mounted() { this.initGraph(); }, methods: { initGraph() { const data = { nodes: [ { id: 'node1', x: 100, y: 100 }, { id: 'node2', x: 200, y: 200 }, { id: 'node3', x: 300, y: 300 }, ], edges: [ { source: 'node1', target: 'node2', type: 'custom-line' }, { source: 'node2', target: 'node3', type: 'custom-line' }, ], }; G6.registerEdge('custom-line', { draw(cfg, group) { const startPoint = cfg.startPoint; const endPoint = cfg.endPoint; const shape = group.addShape('path', { attrs: { stroke: '#333', lineWidth: 2, path: [ ['M', startPoint.x, startPoint.y], ['L', endPoint.x, endPoint.y], ], }, name: 'path-shape', }); return shape; }, }); const graph = new G6.Graph({ container: 'container', width: 500, height: 500, defaultEdge: { type: 'custom-line', }, }); graph.data(data); graph.render(); }, }, }; </script> ``` 3. 在注册Edge时,通过draw方法自定义折线的绘制方式。在draw方法,可以获取到边的起点和终点,然后通过group.addShape('path', {...})方法绘制出折线。最后将折线作为返回值即可。 4. 在Graph实例,可以通过defaultEdge配置项来指定所有边的类型,也可以通过edges配置项来指定单个边的类型。通过type属性来指定边的类型为custom-line即可。 5. 在上面的示例,我们仅仅是绘制了一条直线。如果需要绘制更复杂的折线,可以在path数组添加更多的点来控制折线的形状。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

suoh's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值