G6、X6、Vuedraggble、jsplumb的使用 以ER图为例

直奔主题 你们可以初始化一份JS脚本 把我代码C过去看 阅读性高一些 注释清晰

一、jsplumb 

 // 1、初始化 => jsPlumb.connect用于建立连线 参数有三个 source(必选,连接源的标识,可以为id、element或Endpoint,)、target(必选,连接目标的标识,可以为id、element或Endpoint,)、endpoint(可选,端点的形状)
    // ----------------------------------- 示例
    // jsPlumb.ready(function () {
    //   jsPlumb.connect({
    //     source: 'item_left',
    //     target: 'item_right',
    //     endpoint: 'Dot'
    //   })
    // })

    // 2、拖拽节点(拖拽盒子) => 使用draggable()
    //    注意点 => 似乎盒子必须不能是标准流文档 一定要浮动起来 才可以拖拽Div
    // ----------------------------------- 示例
    //   jsPlumb.ready(function () {
    //   jsPlumb.connect({
    //     source: 'item_left',
    //     target: 'item_right',
    //     endpoint: 'Rectangle'
    //   })

    //   jsPlumb.draggable('item_left')
    //   jsPlumb.draggable('item_right')
    // })

    // 3、其他参数 => connecttor(设置连接线的形状) 、anchor(设置锚点的位置)
    // Bezier: 贝塞尔曲线
    // Flowchart: 具有90度转折点的流程线
    // StateMachine: 状态机
    // Straight: 直线
    // ----------------------------------- 示例
    // jsPlumb.ready(function () {
    //   jsPlumb.connect({
    //     source: 'item_left',
    //     target: 'item_right',
    //     endpoint: 'Rectangle',
    //     connector: ['Bezier'],
    //     anchor: ['Left', 'Right']
    //   })

    //   jsPlumb.draggable('item_left')
    //   jsPlumb.draggable('item_right')
    // })


    // 4、设置连接的默认值(很多连线都是相同设置的情况下,我们可以将配置项抽离出来,作为一个单独的变量,作为connect的第二个参数传入,实际上第二个参数会和第一个参数作为一个整体)
    // ----------------------------------- 示例
    //   let common = {
    //     endpoint: 'Rectangle',
    //     connector: ['Bezier'],
    //     anchor: ['Left', 'Right']
    //   }
    // jsPlumb.ready(function () {
    //   jsPlumb.connect({
    //     source: 'item_left',
    //     target: 'item_right'
    //   }, common)

    //   jsPlumb.draggable('item_left')
    //   jsPlumb.draggable('item_right')
    // })

    // 5、给节点增加样式 => paintStyle(连接线的样式) 、endpointStyle(端点的样式) 作为配置项 卸载common里

    // 6、限制节点拖动区域 => containment(限制节点可拖动的区域) 作为draggable的第二个参数使用
    // ----------------------------------- 示例
    // jsPlumb.draggable('A',{containment: 'parent'})    // {containment: 'parent'}  parent => 父亲  意思为可移动区域为父亲的盒子内
    // jsPlumb.draggable('B',{containment: 'parent'})


    // 7、一个端点如何拖拽出多条连线
    // 默认的情况下maxConnections的值为1 也就是一个端点最多只能拉出一条线 可以设为其他值 
    // 不限制连线数量 将该值设为-1
    // ----------------------------------- 示例
    // let common = {
    //   isSource: true,
    //   isTarget: true,
    //   connector: ['Straight'],
    //   maxConnections: -1
    // }

    // 8、给连接增加点击事件 点击删除连线 jsPlumb.deleteConnection()
    // jsPlumb.bind('click', function (conn, originalEvent) {
    //     if (confirm("确定要删除吗")) {
    //         jsPlumb.deleteConnection(conn)
    //     }
    //   })

    // 9、删除节点,包括节点的相关的连接  参数为 节点id
    // jsPlumb.remove('item_left')


    // 10、连接前的检查,判断是否给建立连接

    // 当链接建立前
    // jsPlumb.bind('beforeDrop', function (info) {
    //   var a = 10
    //   var b = 2
    //   if (a < b) {
    //     console.log('链接会自动建立')
    //     return true // 链接会自动建立
    //   } else {
    //     console.log('链接取消')
    //     return false // 链接不会建立,注意,必须是false
    //   }
    // })

二、Vuedraggable

// vuedraggble插件实现拖拽效果
// 使用draggable组件步骤

// 1、安装依赖 
      yarn add vuedraggable
      npm i -S vuedraggable
      
// 2、组件中 导入并注册 import draggable from 'vuedraggable';
      
// 3、基本参数
      <!-- 
          name        可跨越拖拽的共同类名
          pull:clone 禁止拖入这里
          put:false  禁止拖出这里
          sort:false 禁止拖动排序
          anmition    拖动时的延时动画效果
          filter      不能拖动的类名
          delay       延迟多少ms时拖动,防止用户误操作
          使用draggable组件 v-model绑定数组
          @start="onStart"// =>拖拽开始触发  @end="onEnd" // => 拖拽结束触发
         -->
              
//  示例 => 列表拖拽
      <draggable
          @end="end" => 拖拽结束触发
          @start="move" => 拖拽开始触发
          v-model="menu.children" => 数据结构 使用v-model绑定数据
          :options="draggableOptions"
        >
          <li
            v-for="subMenu in menu.children"
            class="ef-node-menu-li"
            :key="subMenu.id"
            :type="subMenu.type"
          >
            <i :class="subMenu.ico"></i> {{ subMenu.name }}
          </li>
      </draggable>

// 4、注意:vuedraggable新版本废弃了options属性,建议使用v-bind属性作为配置项

vue.draggable 全部事件列表

@start => 开始拖动时触发的事件
@add => 从一个数组拖拽到另外一个数组时触发的事件
@remove => 移除事件
@update => 拖拽变换位置时触发的事件
@end => 拖拽完成时的事件
@choose => 鼠标点击选中要拖拽元素时的事件
@unchoose => 选中后松开鼠标的事件
@sort => 位置变化时的事件
@clone => 从一个数组拖拽到另外一个数组时触发的事件和add不同,clone是复制了数组元素

三、G6/X6 ER图

import { Graph,  Shape } from '@antv/x6'
import { data } from './GraphData'   

 data() {
      return {
       graph:null
      }
    },


// 要在mounted中初始化 因为created中暂未获取dom节点
   mounted(){
      this.init() // 初始化
      this.$bus.$on('addCanvs',(x,y,obj)=>{
        this.addTable(x,y,obj)
      })
    },

 methods:{
      init(){
        //  渲染画布 => 创建一个 Graph 对象 并为其指定一个页面上的绘图容器,并且通常也会在这里指定画布的大小。
        this.graph = new Graph({
            container: document.getElementById('container'),
            width: 800,
            height: 600,
            background: {
                color: '#fffbe6', // 设置画布背景颜色
            },
            grid: {
              size: 20,      // 网格大小 10px
              visible: true, // 渲染网格背景
            },
            
            connecting: {
              router: {
                name: 'er',
                args: {
                  offset: 25,
                  direction: 'H',
                },
              },
              createEdge() {
                return new Shape.Edge({
                  attrs: {
                    line: {
                      stroke: '#A2B1C3',
                      strokeWidth: 2,
                    },
                  },
                })
              },
            },
        })
        Graph.registerPortLayout(
        'erPortPosition',
        (portsPositionArgs) => {
          return portsPositionArgs.map((_, index) => {
            return {
              position: {
                x: 0,
                y: (index + 1) * LINE_HEIGHT,
              },
              angle: 0,
            }
          })
        },
        true,
      )

        // 注册自定义节点
        Graph.registerNode(
          'er-rect', // 注册的节点名
          {
            inherit: 'rect',
            markup: [
              {
                tagName: 'rect',
                selector: 'body',
              },
              {
                tagName: 'text',
                selector: 'label',
              },
            ],
            attrs: {
              rect: {
                strokeWidth: 1,
                stroke: '#5F95FF',
                fill: '#5F95FF',
              },
              label: {
                fontWeight: 'bold',
                fill: '#ffffff',
                fontSize: 12,
              },
            },
            ports: {
              groups: {
                list: {
                  markup: [
                    {
                      tagName: 'rect',
                      selector: 'portBody',
                    },
                    {
                      tagName: 'text',
                      selector: 'portNameLabel',
                    },
                    {
                      tagName: 'text',
                      selector: 'portTypeLabel',
                    },
                  ],
                  attrs: {
                    portBody: {
                      width: NODE_WIDTH,
                      height: LINE_HEIGHT,
                      strokeWidth: 1,
                      stroke: '#5F95FF',
                      fill: '#EFF4FF',
                      magnet: true,
                    },
                    portNameLabel: {
                      ref: 'portBody',
                      refX: 6,
                      refY: 6,
                      fontSize: 10,
                    },
                    portTypeLabel: {
                      ref: 'portBody',
                      refX: 95,
                      refY: 6,
                      fontSize: 10,
                    },
                  },
                  position: 'erPortPosition',
                },
              },
            },
          },
          true, // 重名时是否覆盖,默认为 false 不覆盖(重名时报错)
        )
        // this.graph.zoom(30) => 缩放
        // this.graph.translate(800, 40) => 平移

        // 渲染
        const cells = []
        data.forEach((item) => {
          // 通过图形进行区分push
          if (item.shape === 'edge') {
            // push边的数据
            cells.push(this.graph.createEdge(item))
          } else {
            // push节点的数据
            cells.push(this.graph.createNode(item))
          }
        })
        this.graph.resetCells(cells)
        this.graph.zoomToFit({ padding: 10, maxScale: 1 })
      },
      offset(){
        let offset = {
          top: this.$refs.maxDiv.offsetTop,
          left:  this.$refs.maxDiv.offsetLeft
        }
        return offset
      },
      addTable(x,y,obj){
      // 判断是否拖拽至正确区域位置
      if(x > this.$refs.maxDiv.offsetLeft && y > this.$refs.maxDiv.offsetTop){
        console.log(obj, this);
        this.graph.addNode(obj) // 添加到画布
      } else {
        alert("请拖拽至正确区域")
      }
    }
    }

ER图的data数据来源

export const data =  [
  {
    "id": "1", // String,可选,节点的唯一标识
    "shape": "er-rect", // 图形渲染 => shape 的默认值为 'rect'
    "label": "学生", // String,节点标签
    "width": 150, // Number,可选,节点大小的 width 值
    "height": 24, // Number,可选,节点大小的 height 值
    "position": {  // 设置节点位置
      "x": 24, // Number,必选,节点位置的 x 值
      "y": 150  // Number,必选,节点位置的 y 值
    },
    "ports": [
      {
        "id": "1-1",
        "group": "list",
        "attrs": {
          "portNameLabel": {
            "text": "ID"
          },
          "portTypeLabel": {
            "text": "STRING"
          }
        }
      },
      {
        "id": "1-2",
        "group": "list",
        "attrs": {
          "portNameLabel": {
            "text": "Name"
          },
          "portTypeLabel": {
            "text": "STRING"
          }
        }
      },
      {
        "id": "1-3",
        "group": "list",
        "attrs": {
          "portNameLabel": {
            "text": "Class"
          },
          "portTypeLabel": {
            "text": "NUMBER"
          }
        }
      },
      {
        "id": "1-4",
        "group": "list",
        "attrs": {
          "portNameLabel": {
            "text": "Gender"
          },
          "portTypeLabel": {
            "text": "BOOLEAN"
          }
        }
      }
    ]
  },
  {
    "id": "2",
    "shape": "er-rect",
    "label": "课程",
    "width": 150,
    "height": 24,
    "position": {
      "x": 250,
      "y": 210
    },
    "ports": [
      {
        "id": "2-1",
        "group": "list",
        "attrs": {
          "portNameLabel": {
            "text": "ID"
          },
          "portTypeLabel": {
            "text": "STRING"
          }
        }
      },
      {
        "id": "2-2",
        "group": "list",
        "attrs": {
          "portNameLabel": {
            "text": "Name"
          },
          "portTypeLabel": {
            "text": "STRING"
          }
        }
      },
      {
        "id": "2-3",
        "group": "list",
        "attrs": {
          "portNameLabel": {
            "text": "StudentID"
          },
          "portTypeLabel": {
            "text": "STRING"
          }
        }
      },
      {
        "id": "2-4",
        "group": "list",
        "attrs": {
          "portNameLabel": {
            "text": "TeacherID"
          },
          "portTypeLabel": {
            "text": "STRING"
          }
        }
      },
      {
        "id": "2-5",
        "group": "list",
        "attrs": {
          "portNameLabel": {
            "text": "Description"
          },
          "portTypeLabel": {
            "text": "STRING"
          }
        }
      }
    ]
  },
  {
    "id": "3",
    "shape": "er-rect",
    "label": "老师",
    "width": 150,
    "height": 24,
    "position": {
      "x": 480,
      "y": 350
    },
    "ports": [
      {
        "id": "3-1",
        "group": "list",
        "attrs": {
          "portNameLabel": {
            "text": "ID"
          },
          "portTypeLabel": {
            "text": "STRING"
          }
        }
      },
      {
        "id": "3-2",
        "group": "list",
        "attrs": {
          "portNameLabel": {
            "text": "Name"
          },
          "portTypeLabel": {
            "text": "STRING"
          }
        }
      },
      {
        "id": "3-3",
        "group": "list",
        "attrs": {
          "portNameLabel": {
            "text": "Age"
          },
          "portTypeLabel": {
            "text": "NUMBER"
          }
        }
      }
    ]
  },
  {
    "id": "4",
    "shape": "edge",
    "source": { // String,必须,起始节点 id
      "cell": "1", // 连接源 id
      "port": "1-1" // 连接源 具体id
    },
    "target": { // String,必须,目标节点 id
      "cell": "2", // 目标id
      "port": "2-3" // 目标具体id
    },
    "attrs": {
      "line": {
        "stroke": "#A2B1C3",
        "strokeWidth": 2
      }
    },
    "zIndex": 0
  },
  {
    "id": "5",
    "shape": "edge",
    "source": {
      "cell": "3",
      "port": "3-1"
    },
    "target": {
      "cell": "2",
      "port": "2-4"
    },
    "attrs": {
      "line": {
        "stroke": "#A2B1C3",
        "strokeWidth": 2
      }
    },
    "zIndex": 0
  }
]

四、兄弟传值 兄弟调用方法

// main.js中 挂载全局变量(实例)

Vue.prototype.$bus = new Vue()


// 发送
this.$bus.$emit('方法名',参数)

// 接收 (mounted 钩子里)
    mounted(){
      this.$bus.$on('方法名',(参数)=>{
        事件处理....
      })
    },

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值