VUE中使用Antv.X6实现将侧边导航栏节点拖拽到画布中,并能够将画布保存到缓存中

直接上代码,参考官网的文档安装完之后可以直接运行。

<template>
  <div class="home">
    <div class="left-dragger-nav" id="left-dragger-nav">

    </div>



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

<script lang="ts" setup>
import { Graph,Addon,Shape} from "@antv/x6";

import { onMounted } from "@vue/runtime-core";
var {Rect,Circle} = Shape
const data = {
  // 节点
  nodes: [
    {
      id: "node1", // String,可选,节点的唯一标识
      x: 40, // Number,必选,节点位置的 x 值
      y: 40, // Number,必选,节点位置的 y 值
      width: 80, // Number,可选,节点大小的 width 值
      height: 40, // Number,可选,节点大小的 height 值
      label: "hello", // String,节点标签
      ports: {
        groups: {
          groupA: {
            
            attrs: {
              circle: {
                r: 6,
                magnet: true,
                stroke: "#31d0c6",
                strokeWidth: 2,
                fill: "#fff",
              },
            },
          },
        },
             items: [
      {
        id: 'port1',
        group: 'groupA', // 指定分组名称
         position: 'left'
      },
      {
        id: 'port2',
        group: 'groupA', // 指定分组名称
           position: 'bottom'
      },
      {
        id: 'port3',
        group: 'groupA', // 指定分组名称
         position: 'top'
      },
    ],
      },
     
    },
    {
      id: "node2", // String,节点的唯一标识
      x: 160, // Number,必选,节点位置的 x 值
      y: 180, // Number,必选,节点位置的 y 值
      width: 80, // Number,可选,节点大小的 width 值
      height: 40, // Number,可选,节点大小的 height 值
      label: "world", // String,节点标签
    },
  ],
  // 边
  edges: [
    {
      source: "node1", // String,必须,起始节点 id
      target: "node2", // String,必须,目标节点 id
    },
  ],
};
onMounted(() => {
  const graph = new Graph({
    container: document.getElementById("container") as HTMLElement,
    width: 800,
    height: 600,
    background: {
      color: "#fffbe6", // 设置画布背景颜色
    },
    grid: {
      size: 10, // 网格大小 10px
      visible: true, // 渲染网格背景
    },
  });
  graph.fromJSON(data);




//创建左侧拖拽导航栏


const stencil = new Addon.Stencil({
  target:graph,
  groups:[{name:'group1'},{name:'group2'}],
   collapsable: true,
  stencilGraphWidth: 200,//模板画布宽度
  stencilGraphHeight: 180,//模板画布高度
 
});



(document.getElementById("left-dragger-nav") as HTMLElement).appendChild(stencil.container)
 
      const r = new Rect({
        width: 70,
        height: 40,
        attrs: {
          rect: { fill: '#31D0C6', stroke: '#4B4A67', strokeWidth: 6 },
          text: { text: 'rect', fill: 'white' },
        },
      })
 
      const c = new Circle({
        width: 60,
        height: 60,
        attrs: {
          circle: { fill: '#FE854F', strokeWidth: 6, stroke: '#4B4A67' },
          text: { text: 'ellipse', fill: 'white' },
        },
      })

 const c2 = new Circle({
        width: 60,
        height: 60,
        attrs: {
          circle: { fill: '#4B4A67', 'stroke-width': 6, stroke: '#FE854F' },
          text: { text: 'ellipse', fill: 'white' },
        },
      })
 
      const r2 = new Rect({
        width: 70,
        height: 40,
        attrs: {
          rect: { fill: '#4B4A67', stroke: '#31D0C6', strokeWidth: 6 },
          text: { text: 'rect', fill: 'white' },
        },
      })
 
      const r3 = new Rect({
        width: 70,
        height: 40,
        attrs: {
          rect: { fill: '#31D0C6', stroke: '#4B4A67', strokeWidth: 6 },
          text: { text: 'rect', fill: 'white' },
        },
      })
 
      const c3 = new Circle({
        width: 60,
        height: 60,
        attrs: {
          circle: { fill: '#FE854F', strokeWidth: 6, stroke: '#4B4A67' },
          text: { text: 'ellipse', fill: 'white' },
        },
      })



      //向分组模板画布下添加拖动的元素,记住一定要在创建Stencil的时候添加模板画布的宽度和高度,不然将拖动元素添加进去不会显示
      stencil.load([r, c, c2, r2.clone()], 'group1')
      stencil.load([c2.clone(), r2, r3, c3], 'group2')
    


});




</script>

<style scoped lang="scss">
#left-dragger-nav{
  width:300px;
  border: 1px solid red;
}
#container{
  transform: translateY(500px);
}
</style>

2.实现将画布的数据保存在缓存中,下次加载画布时初始化上一次画布保存的数据,直接上代码,这次的代码在上面的功能上做了扩展所以有点重复

<template>
  <div class="home">
     <button @click="getGraphNodes()" class="graphBtn">保存画布</button>
    <div class="left-dragger-nav" id="left-dragger-nav">

    </div>



    <div class="Graph">
      <div id="container"></div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { Graph,Addon,Shape,Model} from "@antv/x6";

import { onMounted } from "@vue/runtime-core";
var {Rect,Circle} = Shape


//存储初始化保存画布上的节点数据
var nodes=[
 
  ]
//初始化保存画布上的边数据
var edges=[]
  if(sessionStorage.getItem('nodes')){
    //拿到之前画布保存时保存在缓存中的节点数据
    nodes=JSON.parse(sessionStorage.getItem('nodes') as string)
  }
  if(sessionStorage.getItem('edges')){
    //拿到之前画布保存时保存在缓存中的边数据
    edges=JSON.parse(sessionStorage.getItem('edges') as string)
  }


//初始化画布的数据
const graphData = {
  // 节点
  nodes:nodes,//将初始化画布的节点数据赋值
  // 边
  edges:edges,//将初始化画布的边数据赋值
};


//创建存储画布对象的变量
var graph=null

//保存画布 
function getGraphNodes(){
  window.sessionStorage.setItem('nodes',JSON.stringify(graph.getNodes())) //graph.getNodes()为返回画布中所有的节点,然后再存储在session中,初始化画布的时候,再从缓存中拿到节点数据添加到画布的节点属性中
   window.sessionStorage.setItem('edges',JSON.stringify(graph.getEdges()))//graph.getEdges()为返回画布中所有边。边也就是箭头线,然后再存储在session中,再从缓存中拿到边数据添加到画布的边属性中
  // console.log(graph.getEdges())
}
onMounted(() => {
   graph = new Graph({
    container: document.getElementById("container") as HTMLElement,
    width: 800,
    height: 600,
    background: {
      color: "#fffbe6", // 设置画布背景颜色
    },
    grid: {
      size: 10, // 网格大小 10px
      visible: true, // 渲染网格背景
    },
  });
  graph.fromJSON(graphData);//加载画布初始化的数据




//创建左侧拖拽导航栏

const stencil = new Addon.Stencil({
  target:graph,
    getDragNode(node) {
      console.log(node,'--')
      var {attrs,position,shape,size}=node.store.data
    // 这里返回一个新的节点作为拖拽节点
    return graph.createNode({
      position:position,
      width: size.width,
      height: size.height,
      shape: shape,
      attrs:attrs,
      ports:{
            groups: {
      // 输入链接桩群组定义
      in: {
        position: 'top',
        attrs: {
          circle: {
            r: 6,
            magnet: true,
            stroke: '#31d0c6',
            strokeWidth: 2,
            fill: '#fff',
          },
        },
      },
      // 输出链接桩群组定义
      left: {
        position: 'left',
        attrs: {
          circle: {
            r: 6,
            magnet: true,
            stroke: '#31d0c6',
            strokeWidth: 2,
            fill: '#fff',
          },
        },
      },
       // 输出链接桩群组定义
      right: {
        position: 'right',
        attrs: {
          circle: {
            r: 6,
            magnet: true,
            stroke: '#31d0c6',
            strokeWidth: 2,
            fill: '#fff',
          },
        },
      },
      // 输出链接桩群组定义
      out: {
        position: 'bottom',
        attrs: {
          circle: {
            r: 6,
            magnet: true,
            stroke: '#31d0c6',
            strokeWidth: 2,
            fill: '#fff',
          },
        },
      },
    }, items: [
      {
        id: 'port1',
        group: 'in',
      },

      {
        id: 'port3',
        group: 'right',
      },
      {
        id: 'port4',
        group: 'left',
      },
      {
        id: 'port5',
        group: 'out',
      },
    ],
      }
    })
  },
  groups:[{name:'group1'},{name:'group2'}],
   collapsable: true,
  stencilGraphWidth: 200,//模板画布宽度
  stencilGraphHeight: 180,//模板画布高度
 
});




(document.getElementById("left-dragger-nav") as HTMLElement).appendChild(stencil.container)
 
      const r = new Rect({
        width: 70,
        height: 40,
        attrs: {
          rect: { fill: '#31D0C6', stroke: '#4B4A67', strokeWidth: 6 },
          text: { text: 'rect', fill: 'white' },
        },
      })
 
      const c = new Circle({
        width: 60,
        height: 60,
        attrs: {
          circle: { fill: '#FE854F', strokeWidth: 6, stroke: '#4B4A67' },
          text: { text: 'ellipse', fill: 'white' },
        },
      })

 const c2 = new Circle({
        width: 60,
        height: 60,
        attrs: {
          circle: { fill: '#4B4A67', 'stroke-width': 6, stroke: '#FE854F' },
          text: { text: 'ellipse', fill: 'white' },
        },
      })
 
      const r2 = new Rect({
        width: 70,
        height: 40,
        attrs: {
          rect: { fill: '#4B4A67', stroke: '#31D0C6', strokeWidth: 6 },
          text: { text: 'rect', fill: 'white' },
        },
      })
 
      const r3 = new Rect({
        width: 70,
        height: 40,
        attrs: {
          rect: { fill: '#31D0C6', stroke: '#4B4A67', strokeWidth: 6 },
          text: { text: 'rect', fill: 'white' },
        },
      })
 
      const c3 = new Circle({
        width: 60,
        height: 60,
        attrs: {
          circle: { fill: '#FE854F', strokeWidth: 6, stroke: '#4B4A67' },
          text: { text: 'ellipse', fill: 'white' },
        },
      })



      //向分组模板画布下添加拖动的元素,记住一定要在创建Stencil的时候添加模板画布的宽度和高度,不然将拖动元素添加进去不会显示
      stencil.load([r, c, c2, r2.clone()], 'group1')
      stencil.load([c2.clone(), r2, r3, c3], 'group2')



});




























</script>

<style scoped lang="scss">
#left-dragger-nav{
  width:100vw;
  height: 800px;
  border: 1px solid red;
  position: relative;
}
.Graph{

 position: relative;
  border: 1px solid red;
  width: 800px;
}
.graphBtn{
  position: absolute;
  right: 0;
  bottom: 0;
}
</style>
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要在Vue3使用AntV X6实现右键菜单功能,你可以按照以下步骤操作: 1. 安装依赖:在Vue项目安装AntV X6ant-design-vue库。 ``` npm install @antv/x6 ant-design-vue --save ``` 2. 创建右键菜单组件:创建一个Vue组件,作为X6图形编辑器右键菜单的容器。 ```vue <template> <a-dropdown :trigger="['contextmenu']" @visible-change="onVisibleChange"> <a-menu slot="overlay" :style="{ width: '120px' }"> <a-menu-item @click="deleteNode">删除节点</a-menu-item> </a-menu> <div class="x6-contextmenu" ref="container"></div> </a-dropdown> </template> <script> import { defineComponent } from 'vue'; import { Dropdown, Menu, message } from 'ant-design-vue'; export default defineComponent({ name: 'X6ContextMenu', components: { Dropdown, Menu, MenuItem: Menu.Item, }, emits: ['deleteNode'], mounted() { this.menu = this.$refs.container; this.menu.addEventListener('contextmenu', (e) => { e.preventDefault(); e.stopPropagation(); }); }, methods: { onVisibleChange(visible) { if (visible) { this.$emit('contextmenu', this.menu); } }, deleteNode() { this.$emit('deleteNode'); }, }, }); </script> ``` 3. 在X6图形编辑器添加右键菜单:在X6图形编辑器添加右键菜单功能。 ```vue <template> <div class="x6-editor"> <x6-contextmenu @contextmenu="onContextMenu" @deleteNode="deleteNode"></x6-contextmenu> <div class="x6-graph" ref="container"></div> </div> </template> <script> import { defineComponent } from 'vue'; import { Graph, Node } from '@antv/x6'; import X6ContextMenu from './X6ContextMenu.vue'; export default defineComponent({ name: 'X6Editor', components: { X6ContextMenu, }, data() { return { graph: null, }; }, mounted() { this.graph = new Graph({ container: this.$refs.container, grid: true, // 其他配置 }); // 添加节点 const node = this.graph.addNode({ // 节点配置 }); // 右键菜单事件 this.graph.on('contextmenu', ({ x, y }) => { this.$refs.contextmenu.show(x, y); }); }, methods: { onContextMenu(menu) { // 清空菜单 menu.innerHTML = ''; // 添加菜单项 const deleteMenuItem = document.createElement('a-menu-item'); deleteMenuItem.innerHTML = '删除节点'; deleteMenuItem.addEventListener('click', () => { this.deleteNode(); }); menu.appendChild(deleteMenuItem); }, deleteNode() { // 删除节点 this.graph.removeNode(node); }, }, }); </script> ``` 这样就可以在Vue3使用AntV X6实现右键菜单功能了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值