Kaynağa Gözat

组件自动对齐网格,增加吸附效果;

lichunyang 1 ay önce
ebeveyn
işleme
9b72d6d528

+ 11 - 2
src/views/model/vueflow/index.vue

@@ -18,6 +18,7 @@
         @node-double-click="onNodeDoubleClick"
         @node-click="onNodeClick"
         @edge-double-click="onEdgeDoubleClick"
+        @node-drag="onNodeDrag"
       >
         <!-- 自定义节点类型为default的节点 -->
         <template #node-default="props">
@@ -116,7 +117,8 @@ const {
   updateEdgeData,
   onConnectStart,
   updateNode,
-  updateNodeInternals
+  updateNodeInternals,
+  onNodeDrag
 } = useVueFlow()
 
 const { onDragOver, onDrop, onDragLeave, isDragOver } = useDragAndDrop()
@@ -124,7 +126,7 @@ const { onDragOver, onDrop, onDragLeave, isDragOver } = useDragAndDrop()
 const dark = ref(false)
 let vueFlowRef = ref()
 let iconcolor = ref("#000")
-
+const GRID_SIZE = 5;
 const edges = ref([])
 const nodes = ref([])
 let mergedObj = ref("")
@@ -154,6 +156,13 @@ const props = defineProps({
   }
 })
 
+
+// 处理节点拖动时的网格吸附
+onNodeDrag(({ node }) => {
+  node.position.x = Math.round(node.position.x / GRID_SIZE) * GRID_SIZE;
+  node.position.y = Math.round(node.position.y / GRID_SIZE) * GRID_SIZE;
+});
+
 // 旧数据存储
 let prevNodes = [...nodes.value]
 let prevEdges = [...edges.value]

+ 64 - 56
src/views/model/vueflow/useDnD.js

@@ -5,7 +5,7 @@ import { ElMessage, ElButton, ElDialog, ElSelect } from "element-plus"
 import { request, getImage } from "@/utils/request"
 import emitter from "@/utils/emitter"
 import { useProjectStore } from "@/store/project"
-import {nextTick} from "vue" 
+import { nextTick } from "vue"
 
 import tempic from "@/assets/img/temp.png"
 
@@ -122,7 +122,7 @@ export default function useDragAndDrop() {
       }
     }
   }
-  function handleNodeDrop(e) {}
+  function handleNodeDrop(e) { }
   function onDragLeave(e) {
     isDragOver.value = false
   }
@@ -140,70 +140,78 @@ export default function useDragAndDrop() {
    *
    * @param {DragEvent} event
    */
-  async function onDrop(event) {
-    const position = screenToFlowCoordinate({
-      x: event.clientX,
-      y: event.clientY
-    })
-
-    const pid = projectStore.pid
-    const nodeId = getId()
-    const image1 = imagefun()
-    const componentName = image1.idCode
-
-    if (!nameCount[componentName]) {
-      nameCount[componentName] = 0
-    }
+async function onDrop(event) {
+  const GRID_SIZE = 5; // 网格大小,调整为需要的对齐单位(如 10 或 50)
+  const position = screenToFlowCoordinate({
+    x: event.clientX,
+    y: event.clientY
+  });
+
+  // 对齐到网格
+  const alignedX = Math.round(position.x / GRID_SIZE) * GRID_SIZE;
+  const alignedY = Math.round(position.y / GRID_SIZE) * GRID_SIZE;
+
+  const pid = projectStore.pid;
+  const nodeId = getId();
+  const image1 = imagefun();
+  const componentName = image1.idCode;
+
+  if (!nameCount[componentName]) {
+    nameCount[componentName] = 0;
+  }
 
-    const newName = `${componentName}${nameCount[componentName]}`
+  const newName = `${componentName}${nameCount[componentName]}`;
 
-    // 创建初始节点(pcId 和 idCodeser 初始为空)
-    const newNode = {
-      id: nodeId,
-      type: draggedType.value,
-      position,
-      data: {
-        ...image1,
-        uid: newName
-      }
+  // 创建初始节点(使用对齐后的位置)
+  const newNode = {
+    id: nodeId,
+    type: draggedType.value,
+    position: { x: alignedX, y: alignedY },
+    data: {
+      ...image1,
+      uid: newName
     }
+  };
 
-    // 1. 先添加节点到画布
-    addNodes([newNode])
+  // 1. 先添加节点到画布
+  addNodes([newNode]);
 
-    // 2. 立即调整位置(使用 onNodesInitialized 确保节点已渲染)
-    const { off } = onNodesInitialized(() => {
-      updateNode(nodeId, (node) => ({
+  // 2. 调整位置(确保对齐效果保留,居中调整后仍对齐到网格)
+  const { off } = onNodesInitialized(() => {
+    updateNode(nodeId, (node) => {
+      const adjustedX = Math.round((node.position.x - node.dimensions.width / 2) / GRID_SIZE) * GRID_SIZE;
+      const adjustedY = Math.round((node.position.y - node.dimensions.height / 2) / GRID_SIZE) * GRID_SIZE;
+      return {
         ...node,
         position: {
-          x: node.position.x - node.dimensions.width / 2,
-          y: node.position.y - node.dimensions.height / 2
+          x: adjustedX,
+          y: adjustedY
         },
         dimensions: { height: 58, width: 60 }
-      }))
-      off() // 移除监听,避免重复执行
-    })
-
-    // 3. 异步获取 pcId 和 idCodeser,并更新节点
-    try {
-      // 等待 createComponent 完成再继续执行
-      const { pcId, ser, idCode } = await createComponent(pid, nid)
-      updateNode(nodeId, (node) => ({
-        ...node,
-        data: {
-          ...node.data,
-          pcId,
-          idCodeser: `${idCode}${ser}`,
-        }
-      }))
-      updateNodeInternals(nodeId);
-    } catch (err) {
-      console.error("添加组件失败:", err.message)
-      ElMessage.error("添加组件失败")
-      // 如果失败,可以考虑移除节点:
-      // removeNodes([nodeId]);
-    }
+      };
+    });
+    off(); // 移除监听,避免重复执行
+  });
+
+  // 3. 异步获取 pcId 和 idCodeser,并更新节点
+  try {
+    const { pcId, ser, idCode } = await createComponent(pid, nid);
+    updateNode(nodeId, (node) => ({
+      ...node,
+      data: {
+        ...node.data,
+        pcId,
+        idCodeser: `${idCode}${ser}`,
+      }
+    }));
+    updateNodeInternals(nodeId);
+  } catch (err) {
+    console.error("添加组件失败:", err.message);
+    ElMessage.error("添加组件失败");
+    // 如果失败,可以考虑移除节点:
+    // removeNodes([nodeId]);
   }
+}
   return {
     treeobj,
     draggedType,