Ver código fonte

add_contextMenu

ananzhusen 2 anos atrás
pai
commit
4e91043d61
2 arquivos alterados com 179 adições e 36 exclusões
  1. 83 0
      src/views/components/ContextMenu.vue
  2. 96 36
      src/views/components/View.vue

+ 83 - 0
src/views/components/ContextMenu.vue

@@ -0,0 +1,83 @@
+<template>
+  <div class="l-context-menu t-dropdown__menu">
+    <template v-if="props.type === 'anchor'">
+      <t-dropdown-item>
+        <a @click="onAddAnchorHand">
+          <div class="flex">添加手柄 <span class="flex-grow"></span> H</div>
+        </a>
+      </t-dropdown-item>
+      <t-dropdown-item>
+        <a @click="onRemoveAnchorHand">
+          <div class="flex">删除手柄 <span class="flex-grow"></span> D</div>
+        </a>
+      </t-dropdown-item>
+      <t-dropdown-item>
+        <a @click="onToggleAnchorHand">
+          <div class="flex">切换手柄 <span class="flex-grow"></span> Shift</div>
+        </a>
+      </t-dropdown-item>
+    </template>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref } from "vue";
+
+const props = defineProps({
+  type: String,
+});
+const emit = defineEmits(["changeVisible"]);
+
+const onAddAnchorHand = () => {
+  meta2d.addAnchorHand();
+  emit("changeVisible", false);
+};
+
+const onRemoveAnchorHand = () => {
+  meta2d.removeAnchorHand();
+  emit("changeVisible", false);
+};
+
+const onToggleAnchorHand = () => {
+  meta2d.toggleAnchorHand();
+  emit("changeVisible", false);
+};
+</script>
+
+<style lang="postcss" scoped>
+.l-context-menu {
+  position: absolute;
+  display: flex;
+  flex-direction: column;
+  padding: 6px;
+  border-radius: 6px;
+  gap: 2px;
+  background-color: var(--color-background-popup);
+  z-index: 999;
+  .t-dropdown__item {
+    max-width: 240px !important;
+    /* padding: 0;
+    background-color: transparent; */
+
+    &:hover {
+      background-color: var(--color-background-popup-hover);
+    }
+
+    a {
+      width: 150px;
+      display: block;
+      text-decoration: none;
+      color: var(--color);
+
+      label {
+        font-size: 10px;
+        background-color: #ff400030;
+        color: var(--color-bland);
+        padding: 0 6px;
+        margin-left: 4px;
+        border-radius: 2px;
+      }
+    }
+  }
+}
+</style>

+ 96 - 36
src/views/components/View.vue

@@ -146,7 +146,11 @@
         </a>
         <t-dropdown-menu>
           <t-dropdown-item v-for="item in fromArrows">
-            <div class="flex middle" style="height: 30px;" @click="changeFromArrow(item.value)">
+            <div
+              class="flex middle"
+              style="height: 30px"
+              @click="changeFromArrow(item.value)"
+            >
               <svg class="l-icon" aria-hidden="true">
                 <use :xlink:href="item.icon"></use>
               </svg>
@@ -171,7 +175,11 @@
         </a>
         <t-dropdown-menu>
           <t-dropdown-item v-for="item in toArrows">
-            <div class="flex middle" style="height: 30px;" @click="changeToArrow(item.value)">
+            <div
+              class="flex middle"
+              style="height: 30px"
+              @click="changeToArrow(item.value)"
+            >
               <svg class="l-icon" aria-hidden="true">
                 <use :xlink:href="item.icon"></use>
               </svg>
@@ -237,7 +245,15 @@
       </t-tooltip>
     </div>
     <div id="meta2d"></div>
-
+    <ContextMenu
+      :style="{
+        left: contextMenuValue.left,
+        top: contextMenuValue.top,
+      }"
+      v-show="contextMenuVisible"
+      :type="contextMenuType"
+      @changeVisible="changeContextMenuVisible"
+    />
     <t-dialog v-model:visible="connectVisible">
       <p>这是通信对话框</p>
     </t-dialog>
@@ -252,6 +268,7 @@ import {
   deepClone,
   LockState,
   PenType,
+  HoverType,
 } from "@meta2d/core";
 import { onMounted, onUnmounted, watch, ref, reactive } from "vue";
 import { registerBasicDiagram } from "@/services/register";
@@ -274,6 +291,7 @@ import localforage from "localforage";
 import { checkData, Meta2dBackData } from "@/services/utils";
 import { cdn } from "@/services/api";
 import dayjs from "dayjs";
+import ContextMenu from "./ContextMenu.vue";
 
 const router = useRouter();
 const route = useRoute();
@@ -284,25 +302,25 @@ const { select } = useSelection();
 const meta2dOptions: Options = {
   cdn,
   rule: true,
-  background: '#1e2430',
+  background: "#1e2430",
   x: 32,
   y: 32,
   width: 1920,
   height: 1080,
   color: "#bdc7db",
-  disableAnchor:true,
+  disableAnchor: true,
   defaultFormat: { ...defaultFormat },
 };
 onMounted(() => {
-  meta2d = new Meta2d('meta2d', meta2dOptions);
+  meta2d = new Meta2d("meta2d", meta2dOptions);
   registerBasicDiagram();
   open();
   // @ts-ignore
-  meta2d.on('active', active);
+  meta2d.on("active", active);
   // @ts-ignore
-  meta2d.on('inactive', inactive);
+  meta2d.on("inactive", inactive);
   // @ts-ignore
-  meta2d.on('scale', scaleListener);
+  meta2d.on("scale", scaleListener);
   // @ts-ignore
   meta2d.on("add", lineAdd);
   meta2d.on("opened", openedListener);
@@ -316,6 +334,9 @@ onMounted(() => {
 
   //TODO所有编辑栏所做修改
   meta2d.on("components-update-value", autoSave);
+  // @ts-ignore
+  meta2d.on("contextmenu", contextmenu);
+  meta2d.on("click", canvasClick);
 });
 
 const watcher = watch(
@@ -327,7 +348,7 @@ const watcher = watch(
 
 const open = async () => {
   if (route.query.id) {
-    const ret: any = getLe5le2d(route.query.id + '');
+    const ret: any = getLe5le2d(route.query.id + "");
     ret && meta2d.open(ret);
   } else {
     meta2d.open();
@@ -343,21 +364,21 @@ const openedListener = () => {
     fromArrow: canvasFromArrow,
     toArrow: canvasToArrow,
   } = meta2d.store.data;
-  isLock.value = locked||0;
+  isLock.value = locked || 0;
   scale.value = Math.round(canvasScale * 100);
-  fromArrow.value = canvasFromArrow||"";
-  toArrow.value = canvasToArrow||"";
-}
+  fromArrow.value = canvasFromArrow || "";
+  toArrow.value = canvasToArrow || "";
+};
 
 onUnmounted(() => {
   watcher();
   if (meta2d) {
     // @ts-ignore
-    meta2d.off('active', active);
+    meta2d.off("active", active);
     // @ts-ignore
-    meta2d.off('inactive', inactive);
+    meta2d.off("inactive", inactive);
     // @ts-ignore
-    meta2d.off('scale', scaleListener);
+    meta2d.off("scale", scaleListener);
     // @ts-ignore
     meta2d.off("add", lineAdd);
     meta2d.on("opened", openedListener);
@@ -369,6 +390,9 @@ onUnmounted(() => {
     meta2d.off("rotatePens", autoSave);
     meta2d.off("translatePens", autoSave);
     meta2d.off("components-update-value", autoSave);
+    // @ts-ignore
+    meta2d.off("contextmenu", contextmenu);
+    meta2d.off("click", canvasClick);
     meta2d.destroy();
   }
 });
@@ -462,7 +486,7 @@ const connectShow = () => {
   connectVisible.value = true;
 };
 
-const currentLineType = ref('curve');
+const currentLineType = ref("curve");
 const lineTypes = reactive([
   { name: "曲线", icon: "#l-curve2", value: "curve" },
   { name: "线段", icon: "#l-polyline", value: "polyline" },
@@ -564,29 +588,29 @@ const oneDraw = () => {
     if (!alwaysD.value) {
       // meta2d.finishDrawLine();
       // meta2d.drawLine();
-      meta2d.store.options.disableAnchor =true;
+      meta2d.store.options.disableAnchor = true;
     }
   } else {
     oneD.value = true;
     // meta2d.drawLine(meta2d.store.options.drawingLineName);
-    meta2d.store.options.disableAnchor =false;
+    meta2d.store.options.disableAnchor = false;
   }
   if (alwaysD.value) {
     // meta2d.finishDrawLine();
     // meta2d.drawLine();
     oneD.value = false;
     alwaysD.value = false;
-    meta2d.store.options.disableAnchor =true;
+    meta2d.store.options.disableAnchor = true;
   }
 };
 const alwaysDraw = () => {
   alwaysD.value = true;
   // meta2d.drawLine(meta2d.store.options.drawingLineName);
-  meta2d.store.options.disableAnchor =false;
+  meta2d.store.options.disableAnchor = false;
 };
 
 const lineAdd = (pens: Pen[]) => {
-  if (pens.length === 1 && pens[0].name === 'line') {
+  if (pens.length === 1 && pens[0].name === "line") {
     //连线类型
     if (oneD.value && !alwaysD.value) {
       if (meta2d.canvas.drawingLineName) {
@@ -594,7 +618,7 @@ const lineAdd = (pens: Pen[]) => {
         setTimeout(() => {
           // meta2d.finishDrawLine();
           // meta2d.drawLine();
-          meta2d.store.options.disableAnchor =true;
+          meta2d.store.options.disableAnchor = true;
         }, 100);
       }
     }
@@ -603,30 +627,30 @@ const lineAdd = (pens: Pen[]) => {
 
 const onAddShape = (event: DragEvent | MouseEvent, name: string) => {
   let data: any;
-  if (name === 'text') {
+  if (name === "text") {
     data = {
-      text: 'text',
+      text: "text",
       width: 100,
       height: 20,
-      name: 'text',
+      name: "text",
     };
-  } else if (name === 'line') {
+  } else if (name === "line") {
     data = {
       anchors: [
-        { id: '0', x: 0, y: 0.5 },
-        { id: '1', x: 1, y: 0.5 },
+        { id: "0", x: 0, y: 0.5 },
+        { id: "1", x: 1, y: 0.5 },
       ],
       width: 100,
       height: 1,
-      name: 'line',
-      lineName: 'line',
+      name: "line",
+      lineName: "line",
       type: 1,
     };
   }
   if (!(event as DragEvent).dataTransfer) {
     meta2d.canvas.addCaches = deepClone([data]);
   } else {
-    (event as DragEvent).dataTransfer?.setData('Meta2d', JSON.stringify(data));
+    (event as DragEvent).dataTransfer?.setData("Meta2d", JSON.stringify(data));
   }
   event.stopPropagation();
 };
@@ -656,13 +680,49 @@ const preview = async () => {
     await localforage.setItem(localMeta2dDataName, JSON.stringify(data));
   }
   router.push({
-    path: '/preview',
+    path: "/preview",
     query: {
-      r: Date.now() + '',
+      r: Date.now() + "",
       id: data._id,
     },
   });
 };
+
+const contextMenuVisible = ref(false);
+const contextMenuValue = ref({
+  left: "0px",
+  top: "0px",
+});
+const contextMenuType = ref("");
+
+const contextmenu = ({ e, rect }: { e: any; rect: any }) => {
+  contextMenuType.value = "";
+  contextMenuValue.value.left = e.clientX + "px";
+  contextMenuValue.value.top = e.clientY + "px";
+  if (
+    meta2d.store.hoverAnchor &&
+    meta2d.canvas.hoverType === HoverType.LineAnchor
+  ) {
+    contextMenuType.value = "anchor";
+  } else {
+    //其他右键菜单
+  }
+
+  if (!contextMenuVisible.value && contextMenuType.value) {
+    contextMenuVisible.value = true;
+  }
+  if (!contextMenuType.value) {
+    contextMenuVisible.value = false;
+  }
+};
+
+const canvasClick = () => {
+  contextMenuVisible.value = false;
+};
+
+const changeContextMenuVisible = (e: boolean) => {
+  contextMenuVisible.value = e;
+};
 </script>
 <style lang="postcss" scoped>
 .meta2d {
@@ -703,7 +763,7 @@ const preview = async () => {
   #meta2d {
     border-top: 1px solid var(--color-background-input);
     height: calc(100vh - 81px);
-    :deep(.meta2d-map){
+    :deep(.meta2d-map) {
       background: var(--color-background);
     }
   }