<script setup lang="ts"> import { onMounted, reactive } from 'vue'; // type import { X6NodesType, X6EdgesType } from '../../type'; // antv/x6 import { Graph } from '@antv/x6'; const data = reactive({ value: { // 节点 nodes: [ { id: 'node1', // String,可选,节点的唯一标识 shape: 'rect', // 默认值 rect 矩形 x: 0, // Number,必选,节点位置的 x 值 y: 0, // Number,必选,节点位置的 y 值 width: 80, // Number,可选,节点大小的 width 值 height: 40, // Number,可选,节点大小的 height 值 label: '节点1', // String,节点标签 }, { id: 'node2', // String,节点的唯一标识 x: 160, // Number,必选,节点位置的 x 值 y: 180, // Number,必选,节点位置的 y 值 width: 80, // Number,可选,节点大小的 width 值 height: 40, // Number,可选,节点大小的 height 值 label: '节点2', // String,节点标签 }, { id: 'node3', x: 200, y: 200, width: 80, height: 40, label: '节点3', }, ] as X6NodesType[], // 边 edges: [ { source: 'node1', // String,必须,起始节点 id target: 'node2', // String,必须,目标节点 id }, { source: 'node2', target: 'node3', }, ] as X6EdgesType[], }, }); const actDom = reactive({ show: false, x: 0, y: 0, }); const currentNode = reactive({ value: {} as any, }); const state = reactive({ graph: null as any, }); onMounted(() => { initGraph(); }); function initGraph() { let dom = document.getElementById('x6-container') as HTMLElement; const graph = new Graph({ container: dom, background: { color: '#fffbe6', // 设置画布背景颜色 }, grid: { size: 10, // 网格大小 10px visible: true, // 渲染网格背景 }, }); graph.fromJSON(data.value); state.graph = graph; cellClick(graph); nodeContextmenu(graph); blankClick(graph); } function cellClick(graph: any) { graph.on('cell:click', () => { resetActDom(); }); } // 右键点击节点 function nodeContextmenu(graph: any) { graph.on('node:contextmenu', ({ e, x, y, cell, view }: any) => { console.log('e >>>>', e); console.log('x >>>>', x); console.log('y >>>>', y); console.log('cell >>>>', cell); console.log('view >>>>', view); currentNode.value.e = e; currentNode.value.x = x; currentNode.value.y = y; currentNode.value.cell = cell; currentNode.value.view = view; actDom.x = x; actDom.y = y; actDom.show = true; }); } // 点击画布空白区域 function blankClick(graph: any) { graph.on('blank:click', () => { resetActDom(); }); } // 添加子节点 function addChildNode() { console.log('添加子节点 >>>>', currentNode.value); console.log('data >>>>', data); resetActDom(); // state.graph.fromJSON(state.graph.toJSON()); // data.value.nodes.push({ // id: 'node4', // x: 400, // y: 400, // width: 80, // height: 40, // label: '节点4', // }); // data.value.edges.push({ // source: 'node3', // target: 'node4', // }); console.log('序列化 >>>>', state.graph.toJSON()); // state.graph.fromJSON(data.value); } // 删除节点 function delNode() { console.log('删除节点 >>>>', currentNode.value); resetActDom(); } function resetActDom() { actDom.show = false; actDom.x = 0; actDom.y = 0; currentNode.value = {}; } </script> <template> <div class="x6-box"> <div id="x6-container"></div> <div v-if="actDom.show" class="action-box shadow-13" :style="{ transform: `translate(${actDom.x}px, ${actDom.y}px)` }" > <q-list dense separator> <q-item clickable @click="addChildNode"> <q-item-section> 添加子节点 </q-item-section> </q-item> <q-item clickable> <q-item-section @click="delNode"> 删除节点 </q-item-section> </q-item> </q-list> </div> </div> </template> <style lang="scss" scoped> .x6-box { position: relative; } #x6-container { width: 800px; height: 400px; } .action-box { position: absolute; top: 0; left: 0; min-width: 100px; min-height: 64px; border: 1px solid rgba(8, 8, 8, 0.13); background-color: #fff; border-radius: 5px; } </style>