antvX6 - Vue自定义节点,并实现多种画布操作,拖拽、缩放、连线、双击、检索等等

一、 首先 antv x6 分为两个版本  低版本和高版本

  我这里是使用的2.0版本 并且搭配了相关插件 例如:画布的图形变换、地图等

  个人推荐 2.0版本,高版本配置多,可使用相关插件多,但是文档描述小,仍在更新, 低版本文档描述清晰,但是相关插件少

二、antv x6 支持自定义节点! 

          这里要特别注意  虽然支持自定义节点,但是连线,连线桩也自然只能节点之间互连,所以你看我的例子中,想要列表里的子节点也可以实现 互相连接,但是这是自定义节点无法做到的。
          因为此时这一整个盒子就是 一个节点!

三、事件集合

    // 事件集合
    loadEvents(containerRef) {
      // 节点双击
      this.graph.on('node:dblclick', ({ node }) => {
        const data = node.store.data;
        console.log(data);
        this.$router.push({
          path: '/modeling/homeModeling',
          query: {
            id: data.modelingId,
            name: data.name,
            layerTypeId: data.layerTypeId,
            tableType: data.modelingType,
          },
        });
      });
      // 连线双击
      this.graph.on('edge:dblclick', ({ edge }) => {
        // const data = edge.store.data;
        // const { type, id } = data;
        // alert('连线双击');
        // console.log('edge:dbclick', edge);
        // if (type === 'taskNode') {
        //   this.nodeId = id;
        //   this.showRight = true;
        // } else {
        //   this.nodeId = '';
        //   this.showRight = false;
        // }
      });
      // 节点鼠标移入
      this.graph.on(
        'node:mouseenter',
        FunctionExt.debounce(({ node }) => {
          // 添加删除
          // const x = node.store.data.size.width - 10;
          // node.addTools({
          //   name: 'button-remove',
          //   args: {
          //     x: 0,
          //     y: 0,
          //     offset: { x, y: 15 },
          //   },
          // });
        }),
        500,
      );
      this.graph.on('node:port-contextmenu', ({ e }) => {
        // console.log(
        //   'ports',
        //   e,
        //   e.currentTarget.parentElement.getAttribute('port'),
        // );
      });
      // 连接线鼠标移入
      this.graph.on('edge:mouseenter', ({ edge }) => {
        // edge.addTools([
        //   'source-arrowhead',
        //   'target-arrowhead',
        //   {
        //     name: 'button-remove',
        //     args: {
        //       distance: '50%',
        //     },
        //   },
        // ]);
      });
      // 节点鼠标移出
      this.graph.on('node:mouseleave', ({ node }) => {
        // // 移除删除
        // node.removeTools();
      });
      this.graph.on('edge:mouseleave', ({ edge }) => {
        // edge.removeTools();
      });
      this.graph.on('edge:connected', ({ isNew, edge }) => {
        // console.log('connected', edge.source, edge.target);
        // if (isNew) {
        //   // 对新创建的边进行插入数据库等持久化操作
        // }
      });
    },

四、画布初始化

    graphInit() {
      // 容器生成图表
      const containerRef = this.$refs.containerRef;
      const graph = new Graph({
        container: containerRef,
        background: {
          color: '#F1F6F9',
        },
        grid: {
          size: 10, // 网格大小 10px
          visible: true, // 绘制网格,默认绘制 dot 类型网格
          type: 'fixedDot',
          args: {
            color: '#AFB0B1', // 网点颜色
            thickness: 1, // 网点大小
          },
        },
        panning: true, // 画布拖拽
        history: true, // 启动历史记录
        selecting: {
          // 选择与框选
          enabled: true,
          rubberband: true,
          movable: true,
          strict: true,
          showNodeSelectionBox: true, // 显示节点的选择框(才能进行移动)
          modifiers: ['alt'],
        },
        // Scroller 使画布具备滚动、平移、居中、缩放等能力
        scroller: {
          enabled: true,
          pageVisible: true,
          pageBreak: true,
          pannable: true,
        },
        // 鼠标滚轮的默认行为是滚动页面 使用ctrl+滚轮 实现缩放
        mousewheel: {
          enabled: true,
          modifiers: ['ctrl', 'meta'], // +按键为缩放
          minScale: 0.5,
          maxScale: 2,
        },
        snapline: true, // 对齐线

        // 节点连接
        connecting: {
          router: {
            name: 'er',
            args: {
              offset: 25,
              direction: 'H',
            },
          },
          snap: true, // 自动吸附
          allowBlank: false, // 是否允许连接到画布空白位置的点
          allowLoop: false, // 是否允许创建循环连线,即边的起始节点和终止节点为同一节点
          allowNode: false, // 是否允许边链接到节点(非节点上的链接桩)
          createEdge() {
            return new Shape.Edge({
              attrs: {
                line: {
                  stroke: '#1684FC',
                  strokeWidth: 2,
                },
              },
            });
          },
        },
        // 连接桩样式 -- 高亮
        highlighting: {
          magnetAvailable: {
            name: 'stroke',
            args: {
              padding: 4,
              attrs: {
                strokeWidth: 4,
                stroke: '#1684FC',
              },
            },
          },
        },
      });

      // 小地图
      const minimapContainer = this.$refs.minimapContainer;
      graph.use(
        new MiniMap({
          container: minimapContainer,
          width: '250',
          height: '150',
          scalable: true, // 是否可缩放
          minScale: 0.01,
          maxScale: 16,
        }),
      );

      // 图形
      graph.use(
        new Transform({
          enabled: true,
          resizing: map,
        }),
      );

      // 缩放画布内容,使画布内容充满视口
      graph.zoomToFit({ padding: 10, maxScale: 1 });

      // 赋值生成
      this.graph = graph;

      // 事件集合
      this.loadEvents(containerRef);
    },

五、创建Vue自定义节点






六、注册引入Vue自定义节点

1、安装依赖

      "@antv/x6-vue-shape": "2.0.6",

      yarn add antv/[email protected]

2、引入 Vue 自定义组件

      import CustomNode from '../node';

3、引入插件的方法

      import { register } from '@antv/x6-vue-shape'; // vue节点

4、注册节点

        

register({

  shape: 'custom-vue-node',

  component: CustomNode,

});


import CustomNode from '../node';
import { register } from '@antv/x6-vue-shape'; // vue节点


// 注册 Vue component
register({
  shape: 'custom-vue-node',
  component: CustomNode,
});

七、创建节点、创建连线、渲染节点

// 连接线  
const lineNewData = newData.map((item, index) => {
          return {
            id: String(new Date().getTime() + index),
            shape: 'edge',
            // 连接源
            source: {
              cell: item.sourceTableId,
            },
            // 连接目标
            target: {
              cell: item.targetTableId,
            },
            attrs: {
              line: {
                stroke: '#1684FC',
                strokeWidth: 2,
              },
            },
            // 名字
            labels: [
              {
                attrs: {
                  label: {
                    text: item.name || '',
                  },
                },
              },
            ],
            zIndex: 0,
          };
        });

        // 节点
        const nodeData = result.map(item => {
          return {
            ...item,
            id: item.modelingVersionId,
            width: Number(item.width || 300),
            height: Number(item.heigh || 270),
            // 节点类型
            shape: item.shape || 'custom-vue-node',
            position: {
              x: Number(item.posX || this.getRandomInt()),
              y: Number(item.posY || this.getRandomInt()),
            },
          };
        });
        this.erData = [...nodeData, ...lineNewData];

  通过数据 渲染节点

  watch: {
    data(val) {
      const cells = [];
      this.data.forEach(item => {
        console.log(item, item.shape);
        if (item.shape === 'edge') {
          cells.push(this.graph.createEdge(item)); // 创建连线
        } else {
          cells.push(this.graph.createNode(item)); // 创建节点
        }
      });
      // 清空画布并添加用指定的节点/边
      this.graph.resetCells(cells);
    },
  },

八、canvas主页面 全部代码






你可能感兴趣的:(vue.js,数据库,前端)