Browse Source

钢笔编辑功能制作

bill 7 months ago
parent
commit
b56ab9398a

+ 1 - 1
package.json

@@ -23,7 +23,7 @@
     "three": "^0.169.0",
     "uuid": "^11.0.2",
     "vite-plugin-html": "^3.2.2",
-    "vue": "^3.5.12",
+    "vue": "^3.5.13",
     "vue-konva": "^3.1.2"
   },
   "devDependencies": {

+ 82 - 74
pnpm-lock.yaml

@@ -19,30 +19,30 @@ specifiers:
   uuid: ^11.0.2
   vite: ^5.4.9
   vite-plugin-html: ^3.2.2
-  vue: ^3.5.12
+  vue: ^3.5.13
   vue-konva: ^3.1.2
   vue-tsc: ^2.1.6
 
 dependencies:
-  '@element-plus/icons-vue': 2.3.1_vue@3.5.12
+  '@element-plus/icons-vue': 2.3.1_vue@3.5.13
   '@tweenjs/tween.js': 25.0.0
   '@types/node': 22.9.0
   '@types/three': 0.169.0
-  element-plus: 2.8.6_vue@3.5.12
+  element-plus: 2.8.6_vue@3.5.13
   konva: 9.3.16
   localforage: 1.10.0
   mitt: 3.0.1
-  pinia: 2.2.4_yeyu5qkeqf4nsspkw5xf25bg7u
+  pinia: 2.2.4_egv2ww6vjuchfsqp7qchczie5e
   sass: 1.80.4
   stateshot: 1.3.5
   three: 0.169.0
   uuid: 11.0.2
   vite-plugin-html: 3.2.2_vite@5.4.10
-  vue: 3.5.12_typescript@5.6.3
-  vue-konva: 3.1.2_konva@9.3.16+vue@3.5.12
+  vue: 3.5.13_typescript@5.6.3
+  vue-konva: 3.1.2_konva@9.3.16+vue@3.5.13
 
 devDependencies:
-  '@vitejs/plugin-vue': 5.1.4_vite@5.4.10+vue@3.5.12
+  '@vitejs/plugin-vue': 5.1.4_vite@5.4.10+vue@3.5.13
   sass-embedded: 1.80.4
   typescript: 5.6.3
   vite: 5.4.10_sst3kxjepkho23ofqy5hrkujju
@@ -80,12 +80,12 @@ packages:
     engines: {node: '>=10'}
     dev: false
 
-  /@element-plus/icons-vue/2.3.1_vue@3.5.12:
+  /@element-plus/icons-vue/2.3.1_vue@3.5.13:
     resolution: {integrity: sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg==}
     peerDependencies:
       vue: ^3.2.0
     dependencies:
-      vue: 3.5.12_typescript@5.6.3
+      vue: 3.5.13_typescript@5.6.3
     dev: false
 
   /@esbuild/aix-ppc64/0.21.5:
@@ -651,7 +651,7 @@ packages:
     resolution: {integrity: sha512-JGpU6qiIJQKUuVSKx1GtQnHJGxRjtfGIhzO2ilq43VZZS//f1h1Sgexbdk+Lq+7569a6EYhOWrUpIruR/1Enmg==}
     dev: false
 
-  /@vitejs/plugin-vue/5.1.4_vite@5.4.10+vue@3.5.12:
+  /@vitejs/plugin-vue/5.1.4_vite@5.4.10+vue@3.5.13:
     resolution: {integrity: sha512-N2XSI2n3sQqp5w7Y/AN/L2XDjBIRGqXko+eDp42sydYSBeJuSm5a1sLf8zakmo8u7tA8NmBgoDLA1HeOESjp9A==}
     engines: {node: ^18.0.0 || >=20.0.0}
     peerDependencies:
@@ -659,7 +659,7 @@ packages:
       vue: ^3.2.25
     dependencies:
       vite: 5.4.10_sst3kxjepkho23ofqy5hrkujju
-      vue: 3.5.12_typescript@5.6.3
+      vue: 3.5.13_typescript@5.6.3
     dev: true
 
   /@volar/language-core/2.4.8:
@@ -680,39 +680,39 @@ packages:
       vscode-uri: 3.0.8
     dev: true
 
-  /@vue/compiler-core/3.5.12:
-    resolution: {integrity: sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw==}
+  /@vue/compiler-core/3.5.13:
+    resolution: {integrity: sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==}
     dependencies:
       '@babel/parser': 7.26.1
-      '@vue/shared': 3.5.12
+      '@vue/shared': 3.5.13
       entities: 4.5.0
       estree-walker: 2.0.2
       source-map-js: 1.2.1
 
-  /@vue/compiler-dom/3.5.12:
-    resolution: {integrity: sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg==}
+  /@vue/compiler-dom/3.5.13:
+    resolution: {integrity: sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==}
     dependencies:
-      '@vue/compiler-core': 3.5.12
-      '@vue/shared': 3.5.12
+      '@vue/compiler-core': 3.5.13
+      '@vue/shared': 3.5.13
 
-  /@vue/compiler-sfc/3.5.12:
-    resolution: {integrity: sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw==}
+  /@vue/compiler-sfc/3.5.13:
+    resolution: {integrity: sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==}
     dependencies:
       '@babel/parser': 7.26.1
-      '@vue/compiler-core': 3.5.12
-      '@vue/compiler-dom': 3.5.12
-      '@vue/compiler-ssr': 3.5.12
-      '@vue/shared': 3.5.12
+      '@vue/compiler-core': 3.5.13
+      '@vue/compiler-dom': 3.5.13
+      '@vue/compiler-ssr': 3.5.13
+      '@vue/shared': 3.5.13
       estree-walker: 2.0.2
       magic-string: 0.30.12
-      postcss: 8.4.47
+      postcss: 8.4.49
       source-map-js: 1.2.1
 
-  /@vue/compiler-ssr/3.5.12:
-    resolution: {integrity: sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA==}
+  /@vue/compiler-ssr/3.5.13:
+    resolution: {integrity: sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==}
     dependencies:
-      '@vue/compiler-dom': 3.5.12
-      '@vue/shared': 3.5.12
+      '@vue/compiler-dom': 3.5.13
+      '@vue/shared': 3.5.13
 
   /@vue/compiler-vue2/2.7.16:
     resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==}
@@ -734,9 +734,9 @@ packages:
         optional: true
     dependencies:
       '@volar/language-core': 2.4.8
-      '@vue/compiler-dom': 3.5.12
+      '@vue/compiler-dom': 3.5.13
       '@vue/compiler-vue2': 2.7.16
-      '@vue/shared': 3.5.12
+      '@vue/shared': 3.5.13
       alien-signals: 0.2.0
       minimatch: 9.0.5
       muggle-string: 0.4.1
@@ -744,44 +744,44 @@ packages:
       typescript: 5.6.3
     dev: true
 
-  /@vue/reactivity/3.5.12:
-    resolution: {integrity: sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg==}
+  /@vue/reactivity/3.5.13:
+    resolution: {integrity: sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==}
     dependencies:
-      '@vue/shared': 3.5.12
+      '@vue/shared': 3.5.13
 
-  /@vue/runtime-core/3.5.12:
-    resolution: {integrity: sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw==}
+  /@vue/runtime-core/3.5.13:
+    resolution: {integrity: sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==}
     dependencies:
-      '@vue/reactivity': 3.5.12
-      '@vue/shared': 3.5.12
+      '@vue/reactivity': 3.5.13
+      '@vue/shared': 3.5.13
 
-  /@vue/runtime-dom/3.5.12:
-    resolution: {integrity: sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA==}
+  /@vue/runtime-dom/3.5.13:
+    resolution: {integrity: sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==}
     dependencies:
-      '@vue/reactivity': 3.5.12
-      '@vue/runtime-core': 3.5.12
-      '@vue/shared': 3.5.12
+      '@vue/reactivity': 3.5.13
+      '@vue/runtime-core': 3.5.13
+      '@vue/shared': 3.5.13
       csstype: 3.1.3
 
-  /@vue/server-renderer/3.5.12_vue@3.5.12:
-    resolution: {integrity: sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg==}
+  /@vue/server-renderer/3.5.13_vue@3.5.13:
+    resolution: {integrity: sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==}
     peerDependencies:
-      vue: 3.5.12
+      vue: 3.5.13
     dependencies:
-      '@vue/compiler-ssr': 3.5.12
-      '@vue/shared': 3.5.12
-      vue: 3.5.12_typescript@5.6.3
+      '@vue/compiler-ssr': 3.5.13
+      '@vue/shared': 3.5.13
+      vue: 3.5.13_typescript@5.6.3
 
-  /@vue/shared/3.5.12:
-    resolution: {integrity: sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg==}
+  /@vue/shared/3.5.13:
+    resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==}
 
-  /@vueuse/core/9.13.0_vue@3.5.12:
+  /@vueuse/core/9.13.0_vue@3.5.13:
     resolution: {integrity: sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==}
     dependencies:
       '@types/web-bluetooth': 0.0.16
       '@vueuse/metadata': 9.13.0
-      '@vueuse/shared': 9.13.0_vue@3.5.12
-      vue-demi: 0.14.10_vue@3.5.12
+      '@vueuse/shared': 9.13.0_vue@3.5.13
+      vue-demi: 0.14.10_vue@3.5.13
     transitivePeerDependencies:
       - '@vue/composition-api'
       - vue
@@ -791,10 +791,10 @@ packages:
     resolution: {integrity: sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==}
     dev: false
 
-  /@vueuse/shared/9.13.0_vue@3.5.12:
+  /@vueuse/shared/9.13.0_vue@3.5.13:
     resolution: {integrity: sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==}
     dependencies:
-      vue-demi: 0.14.10_vue@3.5.12
+      vue-demi: 0.14.10_vue@3.5.13
     transitivePeerDependencies:
       - '@vue/composition-api'
       - vue
@@ -1012,18 +1012,18 @@ packages:
       jake: 10.9.2
     dev: false
 
-  /element-plus/2.8.6_vue@3.5.12:
+  /element-plus/2.8.6_vue@3.5.13:
     resolution: {integrity: sha512-fk5jB8V3efM02/4roZ5SWOLArgaYXbxEydZLlXSr+KPAwjNyHBlk2+HO5em8YKo5+RLBoHnn6BaThj6IE4nXoQ==}
     peerDependencies:
       vue: ^3.2.0
     dependencies:
       '@ctrl/tinycolor': 3.6.1
-      '@element-plus/icons-vue': 2.3.1_vue@3.5.12
+      '@element-plus/icons-vue': 2.3.1_vue@3.5.13
       '@floating-ui/dom': 1.6.11
       '@popperjs/core': /@sxzz/popperjs-es/2.11.7
       '@types/lodash': 4.17.12
       '@types/lodash-es': 4.17.12
-      '@vueuse/core': 9.13.0_vue@3.5.12
+      '@vueuse/core': 9.13.0_vue@3.5.13
       async-validator: 4.2.5
       dayjs: 1.11.13
       escape-html: 1.0.3
@@ -1032,7 +1032,7 @@ packages:
       lodash-unified: 1.0.3_vpgwo5v3ie2bia5ss74pgoa5ly
       memoize-one: 6.0.0
       normalize-wheel-es: 1.2.0
-      vue: 3.5.12_typescript@5.6.3
+      vue: 3.5.13_typescript@5.6.3
     transitivePeerDependencies:
       - '@vue/composition-api'
     dev: false
@@ -1360,7 +1360,7 @@ packages:
     resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
     engines: {node: '>=8.6'}
 
-  /pinia/2.2.4_yeyu5qkeqf4nsspkw5xf25bg7u:
+  /pinia/2.2.4_egv2ww6vjuchfsqp7qchczie5e:
     resolution: {integrity: sha512-K7ZhpMY9iJ9ShTC0cR2+PnxdQRuwVIsXDO/WIEV/RnMC/vmSoKDTKW/exNQYPI+4ij10UjXqdNiEHwn47McANQ==}
     peerDependencies:
       '@vue/composition-api': ^1.4.0
@@ -1374,8 +1374,8 @@ packages:
     dependencies:
       '@vue/devtools-api': 6.6.4
       typescript: 5.6.3
-      vue: 3.5.12_typescript@5.6.3
-      vue-demi: 0.14.10_vue@3.5.12
+      vue: 3.5.13_typescript@5.6.3
+      vue-demi: 0.14.10_vue@3.5.13
     dev: false
 
   /postcss/8.4.47:
@@ -1386,6 +1386,14 @@ packages:
       picocolors: 1.1.1
       source-map-js: 1.2.1
 
+  /postcss/8.4.49:
+    resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==}
+    engines: {node: ^10 || ^12 || >=14}
+    dependencies:
+      nanoid: 3.3.7
+      picocolors: 1.1.1
+      source-map-js: 1.2.1
+
   /queue-microtask/1.2.3:
     resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
     dev: false
@@ -1794,7 +1802,7 @@ packages:
     resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==}
     dev: true
 
-  /vue-demi/0.14.10_vue@3.5.12:
+  /vue-demi/0.14.10_vue@3.5.13:
     resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==}
     engines: {node: '>=12'}
     hasBin: true
@@ -1806,10 +1814,10 @@ packages:
       '@vue/composition-api':
         optional: true
     dependencies:
-      vue: 3.5.12_typescript@5.6.3
+      vue: 3.5.13_typescript@5.6.3
     dev: false
 
-  /vue-konva/3.1.2_konva@9.3.16+vue@3.5.12:
+  /vue-konva/3.1.2_konva@9.3.16+vue@3.5.13:
     resolution: {integrity: sha512-/CyZSZjmKNED3Pt4XJFmAwv2PAYKBN1X/6AkYKIj+zSnJGnRZ17S+0Q+UzMgziyZ9Qg6yb25ol8XvkAJckHOCA==}
     engines: {node: '>= 4.0.0', npm: '>= 3.0.0'}
     peerDependencies:
@@ -1817,7 +1825,7 @@ packages:
       vue: ^3
     dependencies:
       konva: 9.3.16
-      vue: 3.5.12_typescript@5.6.3
+      vue: 3.5.13_typescript@5.6.3
     dev: false
 
   /vue-tsc/2.1.8_typescript@5.6.3:
@@ -1832,17 +1840,17 @@ packages:
       typescript: 5.6.3
     dev: true
 
-  /vue/3.5.12_typescript@5.6.3:
-    resolution: {integrity: sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg==}
+  /vue/3.5.13_typescript@5.6.3:
+    resolution: {integrity: sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==}
     peerDependencies:
       typescript: '*'
     peerDependenciesMeta:
       typescript:
         optional: true
     dependencies:
-      '@vue/compiler-dom': 3.5.12
-      '@vue/compiler-sfc': 3.5.12
-      '@vue/runtime-dom': 3.5.12
-      '@vue/server-renderer': 3.5.12_vue@3.5.12
-      '@vue/shared': 3.5.12
+      '@vue/compiler-dom': 3.5.13
+      '@vue/compiler-sfc': 3.5.13
+      '@vue/runtime-dom': 3.5.13
+      '@vue/server-renderer': 3.5.13_vue@3.5.13
+      '@vue/shared': 3.5.13
       typescript: 5.6.3

BIN
public/五楼.png


+ 2 - 2
src/constant/mode.ts

@@ -1,8 +1,8 @@
 export enum Mode {
 	// 只读不做任何响应
 	readonly = 'readonly',
-	// 添加模式
-	add = 'add',
+	// 绘制模式
+	draw = 'draw',
 	// 阅读模式
 	viewer = 'viewer',
 	// 处于拖拽,可与update和add共存

+ 1 - 1
src/core/components/arrow/index.ts

@@ -4,7 +4,7 @@ import { ArrowConfig } from "konva/lib/shapes/Arrow";
 import { themeMouseColors } from "@/constant/help-style.ts";
 import { BaseItem, generateSnapInfos, getBaseItem } from "../util.ts";
 import { getMouseColors } from "@/utils/colors.ts";
-import { AddMessage } from "@/core/hook/use-add.ts";
+import { AddMessage } from "@/core/hook/use-draw.ts";
 
 export { default as Component } from "./arrow.vue";
 export { default as TempComponent } from "./temp-arrow.vue";

+ 9 - 4
src/core/components/circle/circle.vue

@@ -35,10 +35,15 @@ const { shape, tData, data, operateMenus, describes } = useComponentStatus<
   defaultStyle,
   transformType: "custom",
   customTransform(callback, shape, data) {
+    let initRadius = data.value.radius;
     const update = (mat: Transform, data: CircleData) => {
-      const { x, y, scaleX } = mat.decompose();
+      const { scaleX, x, y } = mat.decompose();
       if (scaleX !== 1) {
-        return { radius: data.radius * scaleX, x, y };
+        return {
+          radius: data.radius * scaleX,
+          x,
+          y,
+        };
       } else {
         return { x, y };
       }
@@ -48,10 +53,11 @@ const { shape, tData, data, operateMenus, describes } = useComponentStatus<
       openSnap: true,
       getRepShape($shape) {
         const repShape = cloneRepShape($shape).shape;
+        initRadius = data.value.radius;
         return {
           shape: repShape,
           update(data) {
-            repShape.x(data.x).y(data.y).radius(data.radius);
+            repShape.x(data.x).y(data.y).radius(data.radius).scale({ x: 1, y: 1 });
           },
         };
       },
@@ -75,7 +81,6 @@ const { shape, tData, data, operateMenus, describes } = useComponentStatus<
   },
   copyHandler(tf, data) {
     const decTf = tf.decompose();
-    console.log(data, decTf);
     return {
       ...data,
       x: data.x + decTf.x,

+ 1 - 1
src/core/components/circle/index.ts

@@ -7,7 +7,7 @@ import {
   getRectSnapPoints,
 } from "../util.ts";
 import { getMouseColors } from "@/utils/colors.ts";
-import { AddMessage } from "@/core/hook/use-add.ts";
+import { AddMessage } from "@/core/hook/use-draw.ts";
 
 export { default as Component } from "./circle.vue";
 export { default as TempComponent } from "./temp-circle.vue";

+ 1 - 1
src/core/components/icon/index.ts

@@ -2,7 +2,7 @@ import { themeMouseColors } from "@/constant/help-style.ts";
 import { Transform } from "konva/lib/Util";
 import { BaseItem, generateSnapInfos, getBaseItem, getRectSnapPoints } from "../util.ts";
 import { getMouseColors } from "@/utils/colors.ts";
-import { AddMessage } from "@/core/hook/use-add.ts";
+import { AddMessage } from "@/core/hook/use-draw.ts";
 
 export { default as Component } from "./icon.vue";
 export { default as TempComponent } from "./temp-icon.vue";

+ 1 - 1
src/core/components/image/index.ts

@@ -2,7 +2,7 @@ import { Transform } from "konva/lib/Util";
 import { BaseItem, generateSnapInfos, getBaseItem, getRectSnapPoints } from "../util.ts";
 import { getMouseColors } from "@/utils/colors.ts";
 import { imageInfo } from "@/utils/resource.ts";
-import { AddMessage } from "@/core/hook/use-add.ts";
+import { AddMessage } from "@/core/hook/use-draw.ts";
 
 export { default as Component } from "./image.vue";
 export { default as TempComponent } from "./temp-image.vue";

+ 1 - 0
src/core/components/image/temp-image.vue

@@ -25,6 +25,7 @@ const data = computed(() => ({ ...defaultStyle, ...props.data }));
 const image = ref<HTMLImageElement | null>(null);
 const shape = ref<DC<Group>>();
 
+console.log(props.data);
 defineExpose({
   get shape() {
     return shape.value;

+ 1 - 1
src/core/components/line/index.ts

@@ -2,7 +2,7 @@ import { Pos } from "@/utils/math.ts";
 import { themeMouseColors } from "@/constant/help-style.ts";
 import { BaseItem, generateSnapInfos, getBaseItem } from "../util.ts";
 import { getMouseColors } from "@/utils/colors.ts";
-import { AddMessage, MessageAction } from "@/core/hook/use-add.ts";
+import { AddMessage } from "@/core/hook/use-draw.ts";
 
 export { default as Component } from "./line.vue";
 export { default as TempComponent } from "./temp-line.vue";

+ 20 - 0
src/core/components/line/line.vue

@@ -14,6 +14,9 @@ import { LineData, getMouseStyle, defaultStyle } from "./index.ts";
 import { useComponentStatus } from "@/core/hook/use-component.ts";
 import { PropertyUpdate, Operate } from "../../propertys";
 import TempLine from "./temp-line.vue";
+import { EditPen } from "@element-plus/icons-vue";
+import { useInteractiveDrawShapeAPI } from "@/core/hook/use-draw.ts";
+import { useStore } from "@/core/store/index.ts";
 
 const props = defineProps<{ data: LineData }>();
 const emit = defineEmits<{
@@ -27,6 +30,7 @@ const { shape, tData, data, operateMenus, describes } = useComponentStatus({
   props,
   getMouseStyle,
   transformType: "line",
+  // type: "line",
   defaultStyle,
   copyHandler(tf, data) {
     data.points = data.points.map((v) => tf.point(v));
@@ -34,4 +38,20 @@ const { shape, tData, data, operateMenus, describes } = useComponentStatus({
   },
   propertys: ["stroke", "strokeWidth", "dash", "opacity", "ref", "zIndex"],
 });
+
+const draw = useInteractiveDrawShapeAPI();
+const store = useStore();
+operateMenus.push({
+  label: "钢笔编辑",
+  icon: EditPen,
+  handler() {
+    draw.enterDrawShape("line", {
+      ...props.data,
+      getMessages: () => {
+        const line = store.getItemById(props.data.id) as LineData;
+        return line ? line.points : [];
+      },
+    });
+  },
+});
 </script>

+ 4 - 2
src/core/components/line/temp-line.vue

@@ -14,12 +14,14 @@
 <script lang="ts" setup>
 import { defaultStyle, LineData } from "./index.ts";
 import { flatPositions } from "@/utils/shared.ts";
-import { computed, ref } from "vue";
+import { computed, onUnmounted, ref } from "vue";
 import { DC } from "@/deconstruction.js";
 import { Line, LineConfig } from "konva/lib/shapes/Line";
-const props = defineProps<{ data: LineData; addMode?: boolean }>();
+const props = defineProps<{ data: LineData; addMode?: boolean; real?: LineData }>();
 const data = computed(() => ({ ...defaultStyle, ...props.data }));
 
+console.log("hit", props.data.id);
+onUnmounted(() => console.error("un hit", props.data.id));
 const hitFunc: LineConfig["hitFunc"] = (con, shape) => {
   con.beginPath();
   con.moveTo(data.value.points[0].x, data.value.points[0].y);

+ 1 - 1
src/core/components/polygon/index.ts

@@ -2,7 +2,7 @@ import { Pos } from "@/utils/math.ts";
 import { themeMouseColors } from "@/constant/help-style.ts";
 import { BaseItem, generateSnapInfos, getBaseItem } from "../util.ts";
 import { getMouseColors } from "@/utils/colors.ts";
-import { AddMessage, MessageAction } from "@/core/hook/use-add.ts";
+import { AddMessage, MessageAction } from "@/core/hook/use-draw.ts";
 
 export { default as Component } from "./polygon.vue";
 export { default as TempComponent } from "./temp-polygon.vue";

+ 19 - 0
src/core/components/polygon/polygon.vue

@@ -14,6 +14,9 @@ import { PolygonData, getMouseStyle, defaultStyle } from "./index.ts";
 import { useComponentStatus } from "@/core/hook/use-component.ts";
 import { PropertyUpdate, Operate } from "../../propertys";
 import TempLine from "./temp-polygon.vue";
+import { useInteractiveDrawShapeAPI } from "@/core/hook/use-draw.ts";
+import { useStore } from "@/core/store/index.ts";
+import { EditPen } from "@element-plus/icons-vue";
 
 const props = defineProps<{ data: PolygonData }>();
 const emit = defineEmits<{
@@ -34,4 +37,20 @@ const { shape, tData, data, operateMenus, describes } = useComponentStatus({
   },
   propertys: ["fill", "stroke", "strokeWidth", "dash", "opacity", "ref", "zIndex"],
 });
+
+const draw = useInteractiveDrawShapeAPI();
+const store = useStore();
+operateMenus.push({
+  label: "钢笔编辑",
+  icon: EditPen,
+  handler() {
+    draw.enterDrawShape("polygon", {
+      ...props.data,
+      getMessages: () => {
+        const line = store.getItemById(props.data.id) as PolygonData;
+        return line ? line.points : [];
+      },
+    });
+  },
+});
 </script>

+ 1 - 2
src/core/components/polygon/temp-polygon.vue

@@ -17,9 +17,8 @@ import { flatPositions } from "@/utils/shared.ts";
 import { computed, ref } from "vue";
 import { DC } from "@/deconstruction.js";
 import { Line } from "konva/lib/shapes/Line";
-const props = defineProps<{ data: PolygonData; addMode?: boolean }>();
+const props = defineProps<{ data: PolygonData; addMode?: boolean; preDel?: boolean }>();
 const data = computed(() => ({ ...defaultStyle, ...props.data }));
-
 const shape = ref<DC<Line>>();
 defineExpose({
   get shape() {

+ 1 - 1
src/core/components/rectangle/index.ts

@@ -3,7 +3,7 @@ import { themeMouseColors } from "@/constant/help-style.ts";
 import { getMouseColors } from "@/utils/colors.ts";
 import { onlyId } from "@/utils/shared.ts";
 import { BaseItem, generateSnapInfos, getBaseItem } from "../util.ts";
-import { AddMessage } from "@/core/hook/use-add.ts";
+import { AddMessage } from "@/core/hook/use-draw.ts";
 
 export { default as Component } from "./rectangle.vue";
 export { default as TempComponent } from "./temp-rectangle.vue";

+ 1 - 1
src/core/components/text/index.ts

@@ -4,7 +4,7 @@ import { themeMouseColors } from "@/constant/help-style.ts";
 import { BaseItem, generateSnapInfos, getBaseItem, getRectSnapPoints } from "../util.ts";
 import { getMouseColors } from "@/utils/colors.ts";
 import { shallowReactive } from "vue";
-import { AddMessage } from "@/core/hook/use-add.ts";
+import { AddMessage } from "@/core/hook/use-draw.ts";
 
 export { default as Component } from "./text.vue";
 export { default as TempComponent } from "./temp-text.vue";

+ 1 - 1
src/core/components/triangle/index.ts

@@ -2,7 +2,7 @@ import { Pos } from "@/utils/math.ts";
 import { themeMouseColors } from "@/constant/help-style.ts";
 import { BaseItem, generateSnapInfos, getBaseItem } from "../util.ts";
 import { getMouseColors } from "@/utils/colors.ts";
-import { AddMessage } from "@/core/hook/use-add.ts";
+import { AddMessage } from "@/core/hook/use-draw.ts";
 
 export { default as Component } from "./triangle.vue";
 export { default as TempComponent } from "./temp-triangle.vue";

+ 1 - 0
src/core/components/util.ts

@@ -9,6 +9,7 @@ export type BaseItem = {
   zIndex: number;
   opacity: number
   ref: boolean
+  listening?: boolean
 };
 
 export const getBaseItem = (): BaseItem => ({

+ 0 - 1
src/core/history.ts

@@ -44,7 +44,6 @@ export class SingleHistory<T = any> {
       this.history.undo();
       this.syncState();
     }
-    console.log(this.history);
     return this.data;
   }
 

+ 8 - 7
src/core/hook/use-component.ts

@@ -1,9 +1,9 @@
 import { DC, EntityShape } from "@/deconstruction";
-import { computed, EmitFn, isRef, Ref, ref } from "vue";
+import { computed, EmitFn, isRef, reactive, Ref, ref, shallowReactive } from "vue";
 import { useAutomaticData } from "./use-automatic-data";
 import { useMouseMigrateTempLayer, useZIndex } from "./use-layer";
 import { useAnimationMouseStyle } from "./use-mouse-status";
-import { DrawItem } from "../components";
+import { components, DrawItem, ShapeType } from "../components";
 import { useMatCompTransformer, useLineTransformer } from "./use-transformer";
 import { useGetShapeCopyTransform } from "./use-copy";
 import { Delete, DocumentCopy } from "@element-plus/icons-vue";
@@ -24,6 +24,7 @@ export type UseComponentStatusProps<
   S extends EntityShape
 > = {
   emit: Emit<T>;
+  type?: ShapeType,
   props: { data: T };
   getMouseStyle: any;
   defaultStyle: any;
@@ -78,18 +79,18 @@ export const useComponentStatus = <S extends EntityShape, T extends DrawItem>(
 
   useZIndex(shape, data);
   useMouseMigrateTempLayer(shape);
-
+  const name = args.type ? components[args.type].shapeName : ''
   const getCopyTransform = useGetShapeCopyTransform(shape);
-  const operateMenus = [
+  const operateMenus = shallowReactive([
     {
-      label: "删除",
+      label: `删除${name}`,
       icon: Delete,
       handler() {
         emit("delShape");
       },
     },
     {
-      label: "复制",
+      label: `复制${name}`,
       icon: DocumentCopy,
       handler() {
         const transform = getCopyTransform();
@@ -101,7 +102,7 @@ export const useComponentStatus = <S extends EntityShape, T extends DrawItem>(
         emit("addShape", copyData);
       },
     },
-  ];
+  ]);
 
   const describes = mergeDescribes(data, defaultStyle, propertys || []);
 

+ 88 - 51
src/core/hook/use-add.ts

@@ -1,4 +1,4 @@
-import { h, nextTick, reactive, ref, watch, watchEffect } from "vue";
+import { computed, h, nextTick, reactive, ref, watch, watchEffect } from "vue";
 import {
   installGlobalVar,
   useCan,
@@ -10,12 +10,13 @@ import {
 import {
   Area,
   InteractiveHook,
+  InteractivePreset,
   useInteractiveAreas,
   useInteractiveDots,
   useInteractiveProps,
 } from "./use-interactive";
 import { Mode } from "@/constant/mode";
-import { mergeFuns } from "@/utils/shared";
+import { copy, mergeFuns } from "@/utils/shared";
 import {
   Components,
   components,
@@ -26,7 +27,7 @@ import {
   SnapPoint,
 } from "../components";
 import { useConversionPosition } from "./use-coversion-position";
-import { eqPoint, lineInner, linePointLen, Pos, zeroEq } from "@/utils/math";
+import { eqPoint, lineInner, Pos } from "@/utils/math";
 import { useCustomSnapInfos, useSnap } from "./use-snap";
 import { generateSnapInfos } from "../components/util";
 import { useStore, useStoreRenderProcessors } from "../store";
@@ -53,7 +54,7 @@ export type AddMessage<T extends ShapeType> = {
   action: MessageAction;
 };
 
-export const useInteractiveAddShapeAPI = installGlobalVar(() => {
+export const useInteractiveDrawShapeAPI = installGlobalVar(() => {
   const mode = useMode();
   const can = useCan();
   const interactiveProps = useInteractiveProps();
@@ -63,7 +64,7 @@ export const useInteractiveAddShapeAPI = installGlobalVar(() => {
   const enter = () => {
     if (!isEnter) {
       isEnter = true;
-      mode.push(Mode.add);
+      mode.push(Mode.draw);
     }
   };
   const leave = () => {
@@ -80,7 +81,7 @@ export const useInteractiveAddShapeAPI = installGlobalVar(() => {
       data: PayData<T>,
       pixel = false
     ) => {
-      if (!can.addMode) {
+      if (!can.drawMode) {
         throw "当前状态不允许添加";
       }
       enter();
@@ -96,34 +97,34 @@ export const useInteractiveAddShapeAPI = installGlobalVar(() => {
         operate: { single: true, immediate: true, data },
       };
     },
-    enterMouseAddShape: async <T extends ShapeType>(
+    enterDrawShape: async <T extends ShapeType>(
       shapeType: T,
-      preset: Partial<DrawItem<T>> = {},
+      preset: InteractivePreset<T>["preset"] = {},
       single = false
     ) => {
       if (isEnter) {
         leave();
         await new Promise((resolve) => setTimeout(resolve, 16));
       }
-      if (!can.addMode || mode.include(Mode.add)) {
+      if (!can.drawMode || mode.include(Mode.draw)) {
         throw "当前状态不允许添加";
       }
-      enter();
       interactiveProps.value = {
         type: shapeType,
         preset,
         operate: { single },
         callback: leave,
       };
+      enter();
     },
-    quitMouseAddShape: () => {
+    quitDrawShape: () => {
       leave();
       interactiveProps.value = void 0;
     },
   };
 });
 
-export const useIsAddRunning = (shapeType?: ShapeType) => {
+export const useDrawRunning = (shapeType?: ShapeType) => {
   const stage = useStage();
   const mode = useMode();
   const interactiveProps = useInteractiveProps();
@@ -132,8 +133,8 @@ export const useIsAddRunning = (shapeType?: ShapeType) => {
   const updateIsRunning = () => {
     const isRun = !!(
       stage.value &&
-      mode.include(Mode.add) &&
-      (!shapeType || shapeType === interactiveProps.value?.type)
+      mode.include(Mode.draw) &&
+      shapeType === interactiveProps.value?.type
     );
 
     if (isRunning.value !== isRun) {
@@ -194,7 +195,7 @@ const usePointBeforeHandler = (enableTransform = false, enableSnap = false) => {
   };
 };
 
-const useInteractiveAddTemp = <T extends ShapeType>({
+const useInteractiveDrawTemp = <T extends ShapeType>({
   type,
   useIA,
   refSelf,
@@ -207,8 +208,8 @@ const useInteractiveAddTemp = <T extends ShapeType>({
   enter?: () => void;
   quit?: () => void;
 }) => {
-  const { quitMouseAddShape } = useInteractiveAddShapeAPI();
-  const isRuning = useIsAddRunning(type);
+  const { quitDrawShape } = useInteractiveDrawShapeAPI();
+  const isRuning = useDrawRunning(type);
   const items = reactive([]) as DrawItem<T>[];
   const obj = components[type] as Components[T];
   const beforeHandler = usePointBeforeHandler(true, true);
@@ -226,7 +227,7 @@ const useInteractiveAddTemp = <T extends ShapeType>({
     quit: () => {
       items.length = 0;
       processorIds.length = 0;
-      quitMouseAddShape();
+      quitDrawShape();
       clear();
       quit && quit();
     },
@@ -298,31 +299,35 @@ const useInteractiveAddTemp = <T extends ShapeType>({
 };
 
 // 拖拽面积确定组件
-export const useInteractiveAddAreas = <T extends ShapeType>(type: T) => {
+export const useInteractiveDrawAreas = <T extends ShapeType>(type: T) => {
   const cursor = useCursor();
-  return useInteractiveAddTemp({
+  let isEnter = false;
+  return useInteractiveDrawTemp({
     type,
     useIA: useInteractiveAreas,
     refSelf: type === "arrow",
     enter() {
+      isEnter = true;
       cursor.push("crosshair");
     },
     quit() {
-      cursor.pop();
+      isEnter && console.log("quit");
     },
   });
 };
 
-export const useInteractiveAddDots = <T extends ShapeType>(type: T) => {
+export const useInteractiveDrawDots = <T extends ShapeType>(type: T) => {
   const cursor = useCursor();
-  return useInteractiveAddTemp({
+  let isEnter = false;
+  return useInteractiveDrawTemp({
     type,
     useIA: useInteractiveDots,
     enter() {
+      isEnter = true;
       cursor.push(penA);
     },
     quit() {
-      cursor.pop();
+      isEnter && cursor.pop();
     },
   });
 };
@@ -350,6 +355,7 @@ export const penUpdatePoints = <T extends Pos>(
       if (!isStart && !isLast) {
         points.splice(i--, 1);
         oper = "del";
+        repeatStart = false;
       } else if ((oper !== "del" && isLast) || isStart) {
         oper = "no";
         if (isStart) {
@@ -360,13 +366,13 @@ export const penUpdatePoints = <T extends Pos>(
   }
   if (oper === "del" || oper === "no") {
     if (repeatStart) {
-      const change = points.length > 2
-      return { 
-        points, 
-        oper, 
+      const change = points.length > 2;
+      return {
+        points,
+        oper,
         cur: change ? cur : resetCur(),
-        unchanged: !change
-      }; 
+        unchanged: !change,
+      };
     }
     return { points, oper, cur: repeatStart ? cur : resetCur() };
   }
@@ -384,25 +390,21 @@ export const penUpdatePoints = <T extends Pos>(
 };
 
 // 钢笔添加
-export const useInteractiveAddPen = <T extends ShapeType>(type: T) => {
-  const { quitMouseAddShape } = useInteractiveAddShapeAPI();
-  const isRuning = useIsAddRunning(type);
-  const items = reactive([]) as DrawItem<T>[];
+export const useInteractiveDrawPen = <T extends ShapeType>(type: T) => {
+  const { quitDrawShape } = useInteractiveDrawShapeAPI();
+  const isRuning = useDrawRunning(type);
   const obj = components[type] as Components[T];
   const beforeHandler = usePointBeforeHandler(true, true);
   const history = useHistory();
   const processors = useStoreRenderProcessors();
   const store = useStore();
   const downKeys = useDownKeys();
+  const free = computed(() => downKeys.has("Control"));
   const processorIds = processors.register(() => {
     return (props: any) => h(DrawShape, { ...props, show: false });
   });
 
-  let prev: Pos;
-  let firstEntry = true;
   // 可能历史空间会撤销 重做更改到正在绘制的组件
-  const messages = useHistoryAttach<Pos[]>(`${type}-pen`, isRuning, []);
-
   const currentCursor = ref(penA);
   const cursor = useCursor();
   const ia = useInteractiveDots({
@@ -417,25 +419,49 @@ export const useInteractiveAddPen = <T extends ShapeType>(type: T) => {
     quit: () => {
       items.length = 0;
       processorIds.length = 0;
-      quitMouseAddShape();
+      quitDrawShape();
       beforeHandler.clear();
       cursor.pop();
     },
     beforeHandler: (p) => {
       beforeHandler.clear();
-      return beforeHandler.transform(p, prev);
+      const pa = beforeHandler.transform(p, prev);
+      currentIsDel && beforeHandler.clear();
+      return pa;
     },
   });
 
+  const shape = computed(
+    () =>
+      ia.isRunning.value &&
+      typeof ia.preset?.id === "string" &&
+      ia.preset?.id &&
+      ia.preset.getMessages &&
+      store.getItemById(ia.preset.id)
+  );
+  const items = reactive([]) as DrawItem<T>[];
+  const messages = useHistoryAttach<Pos[]>(
+    `${type}-pen`,
+    isRuning,
+    shape.value ? ia.preset!.getMessages! as any : () => [],
+    true
+  );
+  let prev: Pos;
+  let firstEntry = true;
+  let currentIsDel = false;
+
+  if (shape.value) {
+    processorIds.push(shape.value.id);
+    items[0] = copy(shape.value) as DrawItem<T>;
+    firstEntry = false;
+  }
+
   const getAddMessage = (cur: Pos) => {
     let consumed = messages.value;
     currentCursor.value = penA;
     let pen: null | ReturnType<typeof penUpdatePoints> = null;
-    if (!downKeys.has("Control")) {
+    if (!free.value) {
       pen = penUpdatePoints(messages.value, cur);
-      if (pen.oper === "del") {
-        currentCursor.value = penR;
-      }
       consumed = pen.points;
       cur = pen.cur;
     }
@@ -447,6 +473,14 @@ export const useInteractiveAddPen = <T extends ShapeType>(type: T) => {
       action: firstEntry ? MessageAction.add : MessageAction.replace,
     } as any;
   };
+  const setMessage = (cur: Pos) => {
+    const { pen, ...msg } = getAddMessage(cur);
+    if ((currentIsDel = pen?.oper === "del")) {
+      currentCursor.value = penR;
+      beforeHandler.clear();
+    }
+    return msg;
+  };
   const pushMessages = (cur: Pos) => {
     const { pen } = getAddMessage(cur);
     if (pen) {
@@ -458,7 +492,7 @@ export const useInteractiveAddPen = <T extends ShapeType>(type: T) => {
     } else {
       messages.value.push(cur);
     }
-    
+
     return !pen?.unchanged;
   };
 
@@ -470,7 +504,7 @@ export const useInteractiveAddPen = <T extends ShapeType>(type: T) => {
     }
     let item: any = items.length === 0 ? null : items[0];
     if (!item) {
-      item = obj.interactiveToData(getAddMessage(dot), ia.preset);
+      item = obj.interactiveToData(setMessage(dot), ia.preset);
       if (!item) return;
       items[0] = item = reactive(item);
     }
@@ -481,17 +515,19 @@ export const useInteractiveAddPen = <T extends ShapeType>(type: T) => {
     }
 
     const update = () => {
-      obj.interactiveFixData(item, getAddMessage(dot));
+      obj.interactiveFixData(item, setMessage(dot));
+      // console.log(JSON.parse(JSON.stringify(item)))
     };
 
     const stop = mergeFuns(
+      watch(free, update),
       watch(dot, update, { immediate: true, deep: true }),
       watch(
         messages,
         () => {
           if (!messages.value) return;
           if (messages.value.length === 0) {
-            quitMouseAddShape();
+            quitDrawShape();
           } else {
             update();
           }
@@ -505,6 +541,7 @@ export const useInteractiveAddPen = <T extends ShapeType>(type: T) => {
         const isChange = pushMessages(dot);
         if (isChange) {
           if (firstEntry) {
+            console.error(firstEntry);
             processorIds.push(item.id);
             history.preventTrack(() => store.addItem(type, cItem));
           } else {
@@ -533,10 +570,10 @@ export const useInteractiveAddPen = <T extends ShapeType>(type: T) => {
 export const useInteractiveAdd = <T extends ShapeType>(type: T) => {
   const obj = components[type];
   if (obj.addMode === "dots") {
-    return useInteractiveAddPen(type);
+    return useInteractiveDrawPen(type);
   } else if (obj.addMode === "area") {
-    return useInteractiveAddAreas(type);
+    return useInteractiveDrawAreas(type);
   } else {
-    return useInteractiveAddDots(type);
+    return useInteractiveDrawDots(type);
   }
 };

+ 2 - 2
src/core/hook/use-expose.ts

@@ -4,7 +4,7 @@ import { useInteractiveProps } from "./use-interactive.ts";
 import { useStore } from "../store/index.ts";
 import { useViewer } from "./use-viewer.ts";
 import { useGlobalResize } from "./use-event.ts";
-import { useInteractiveAddShapeAPI } from "./use-add.ts";
+import { useInteractiveDrawShapeAPI } from "./use-draw.ts";
 import { useHistory } from "./use-history.ts";
 
 type PickParams<K extends keyof Stage, O extends string> = Stage[K]  extends (...args: any) => any ?  Omit<Required<Parameters<Stage[K]>>[0], O> : never
@@ -36,7 +36,7 @@ export const useExpose = () => {
 	}
 
 	return {
-		...useInteractiveAddShapeAPI(),
+		...useInteractiveDrawShapeAPI(),
 		get stage()  {
 			const $store = stage.value!.getStage()
 			return $store

+ 14 - 5
src/core/hook/use-global-vars.ts

@@ -152,7 +152,7 @@ export const useCan = installGlobalVar(() => {
   // 可以进入拖拽模式
   const dragMode = computed(() => {
     if (!mouse.value || mode.include(Mode.viewer) || key.has(' ')) return false;
-    return mode.include(Mode.add) || mode.include(Mode.update)
+    return mode.include(Mode.draw) || mode.include(Mode.update)
   })
 
   // 是否在视图模式
@@ -166,14 +166,14 @@ export const useCan = installGlobalVar(() => {
   // 可以进入编辑模式
   const editMode = computed(() => mouse.value && mode.include(Mode.viewer))
 
-  // 可以进入添加模式
-  const addMode = computed(() => mouse.value && mode.include(Mode.viewer))
+  // 可以进入绘制模式
+  const drawMode = computed(() => mouse.value && mode.include(Mode.viewer))
 
 
   return reactive({
     viewMouseReact: mouse,
     viewMode,
-    addMode,
+    drawMode,
     mouseReact,
     editMode,
     dragMode,
@@ -228,6 +228,15 @@ export const useTransformIngShapes = installGlobalVar(
 
 
 export const useCursor = installGlobalVar(
-  () => stackVar('default'),
+  () => {
+    const cursur = stackVar('default')
+
+    return {
+      var: cursur,
+      onDestroy: () => {
+
+      }
+    }
+  },
   Symbol('cursor')
 )

+ 8 - 5
src/core/hook/use-history.ts

@@ -35,9 +35,9 @@ class DrawHistory {
 
   constructor(renderer: (data: string) => void) {
     this.renderer = ({ data, attachs }: HistoryItem) => {
-      this.bus.emit("attachs", attachs ? JSON.parse(attachs) : {});
       renderer(data);
       this.bus.emit("renderer");
+      this.bus.emit("attachs", attachs ? JSON.parse(attachs) : {});
     };
   }
   
@@ -133,11 +133,11 @@ export const useHistory = installGlobalVar(() => {
 export const useHistoryAttach = <T>(
   name: string,
   isRuning: Ref<boolean> = ref(true),
-  init: T | null = null,
+  getInit: () => T,
   cleanup = true
 ) => {
   const history = useHistory();
-  const current = ref<T>(init ? copy(init) : init!);
+  const current = ref<T>(copy(getInit()!));
   const setIds = [] as string[]
 
   const addSetIds = () => setIds.push(history.currentId)
@@ -145,16 +145,18 @@ export const useHistoryAttach = <T>(
     history.setPushAttach(name, current.value);
   };
   const attachsHandler = (attachs: any) => {
-    current.value = attachs && attachs[name] ? attachs[name] : copy(init);
+    current.value = attachs && attachs[name] ? attachs[name] : getInit();
   };
   const cleanupAttach = () => {
     setIds.forEach(id => history.clearHistoryAttach(id, name))
     setIds.length = 0
   }
 
+  console.log('isRun1', isRuning.value)
   watch(
     isRuning,
     (isRun, _, onCleanup) => {
+      console.log('isRun', isRun)
       if (!isRun) return;
       history.bus.on("push", pushHandler);
       history.bus.on("attachs", attachsHandler);
@@ -164,8 +166,9 @@ export const useHistoryAttach = <T>(
       }
 
       onCleanup(() => {
+        console.log('clear')
         history.bus.off("push", pushHandler);
-        history.bus.off("attachs", pushHandler);
+        history.bus.off("attachs", attachsHandler);
         current.value = void 0;
         
         if (cleanup) {

+ 1 - 1
src/core/hook/use-interactive.ts

@@ -14,7 +14,7 @@ import { Mode } from "@/constant/mode.ts";
 export type InteractivePreset<T extends ShapeType = ShapeType> = {
   type: T;
   callback?: () => void;
-  preset?: Partial<DrawItem<T>>;
+  preset?: Partial<DrawItem<T>> & { getMessages?: () => Pos[] | Area[] };
   operate?: {
     immediate?: boolean;
     single?: boolean;

+ 53 - 30
src/core/propertys/hover-operate.vue

@@ -8,25 +8,32 @@
         class="propertys-controller"
         ref="layout"
       >
-        <div class="item" v-for="menu in menus" @click="menu.handler">
-          <ElButton type="primary" link :icon="menu.icon" size="small">
+        <!-- <div class="item" v-for="menu in menus" @click="menu.handler">
+          <ElButton type="primary" link :icon="menu.icon">
             {{ menu.label }}
           </ElButton>
-        </div>
+        </div> -->
+
+        <ElMenu>
+          <ElMenuItem v-for="menu in menus" @click="menu.handler">
+            <el-icon><component :is="menu.icon" /></el-icon>
+            <span>{{ menu.label }}</span>
+          </ElMenuItem>
+        </ElMenu>
       </div>
     </transition>
   </Teleport>
 </template>
 
 <script lang="ts" setup>
-import { computed, nextTick, ref, watch } from "vue";
+import { computed, nextTick, ref, watch, watchEffect } from "vue";
 import { useStage, useTransformIngShapes } from "../hook/use-global-vars.ts";
 import { DC, EntityShape } from "@/deconstruction.js";
 import { useMouseShapeStatus } from "../hook/use-mouse-status.ts";
 import { useViewerTransformConfig } from "../hook/use-viewer.ts";
 import { Transform } from "konva/lib/Util";
 import { DomMountId } from "@/constant/index.ts";
-import { ElButton } from "element-plus";
+import { ElMenu, ElIcon, ElMenuItem } from "element-plus";
 
 const props = defineProps<{
   target: DC<EntityShape> | undefined;
@@ -38,13 +45,31 @@ const layout = ref<HTMLDivElement>();
 const stage = useStage();
 const status = useMouseShapeStatus(computed(() => props.target));
 const transformIngShapes = useTransformIngShapes();
+const rightClick = ref(false);
+
+watchEffect((onCleanup) => {
+  const dom = stage.value?.getStage().container();
+  if (!dom) return;
+  const clickHandler = (ev: MouseEvent) => {
+    rightClick.value = ev.button === 2 && status.value.hover;
+  };
+
+  dom.addEventListener("contextmenu", clickHandler);
+  dom.addEventListener("pointerdown", clickHandler);
+  onCleanup(() => {
+    dom.removeEventListener("contextmenu", clickHandler);
+    dom.removeEventListener("pointerdown", clickHandler);
+  });
+});
+
 const hidden = computed(
   () =>
     !stage.value?.getStage() ||
     !props.target?.getNode() ||
-    !status.value.hover ||
-    status.value.active ||
-    transformIngShapes.value.length !== 0
+    // !status.value.hover ||
+    // status.value.active ||
+    // transformIngShapes.value.length !== 0
+    !rightClick.value
 );
 
 const move = new Transform();
@@ -108,7 +133,7 @@ const resetPointer = () => {
     return;
   }
   clearTimeout(timeout);
-  timeout = setTimeout(calcPointer, 500);
+  timeout = setTimeout(calcPointer, 16);
 };
 
 watch(hidden, resetPointer);
@@ -119,7 +144,7 @@ watch(useViewerTransformConfig(), () => {
 // watch(() => props.data, resetPointer);
 </script>
 
-<style lang="scss" scoped>
+<style lang="scss">
 .propertys-controller {
   pointer-events: none;
   position: absolute;
@@ -129,33 +154,31 @@ watch(useViewerTransformConfig(), () => {
   left: 0;
   top: 0;
   overflow: hidden;
-  padding: 6px 12px;
   color: #303133;
-  max-width: 240px;
-  font-size: 12px;
-  max-height: 50px;
   display: flex;
+  flex-direction: column;
   align-items: center;
   box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.12);
   min-width: 10px;
+  padding: 5px 0;
+  pointer-events: all;
+  font-size: 14px;
+  border: 1px solid var(--el-border-color-light);
+  box-shadow: var(--el-dropdown-menu-box-shadow);
+  background-color: var(--el-bg-color-overlay);
+  border-radius: var(--el-border-radius-base);
+  --el-menu-base-level-padding: 16px;
+  --el-menu-item-height: 32px;
+  --el-menu-item-font-size: 14px;
 
-  .item {
-    pointer-events: all;
-    display: flex;
-    flex: 0 0 auto;
+  .el-menu-item {
     align-items: center;
-    pointer-events: all;
-
-    &:not(:first-child) {
-      &::before {
-        display: block;
-        flex: 0 0 auto;
-        content: "|";
-        opacity: 0.7;
-        margin-left: 4px;
-        margin-right: 4px;
-      }
-    }
+    padding: 5px 16px 5px 6px !important;
+    color: var(--el-text-color-regular);
+  }
+  .el-menu-item [class^="el-icon"] {
+    margin: 0;
+    font-size: 1em;
   }
 }
 

+ 4 - 1
src/core/renderer/draw-group.vue

@@ -4,16 +4,19 @@
     v-for="item in tempItems"
     temp
     :key="item.id"
+    :real="store.getItemById(item.id)"
     addMode
   />
 </template>
 
 <script setup lang="ts">
 import { ShapeType, components } from "../components";
-import { useInteractiveAdd } from "../hook/use-add.ts";
+import { useInteractiveAdd } from "../hook/use-draw.ts";
+import { useStore } from "../store/index.ts";
 
 const props = defineProps<{ type: ShapeType }>();
 const tempItems = useInteractiveAdd(props.type);
 const type = props.type;
 const ShapeComponent = components[type].TempComponent || components[type].Component;
+const store = useStore();
 </script>

+ 27 - 6
src/core/renderer/renderer.vue

@@ -16,7 +16,7 @@
       </v-layer>
       <!--	临时组,提供临时绘画,以及高频率渲染	-->
       <v-layer :config="viewerConfig" id="temp">
-        <template v-if="mode.include(Mode.add)">
+        <template v-if="mode.include(Mode.draw)">
           <TempShapeGroup v-for="type in types" :type="type" :key="type" />
         </template>
       </v-layer>
@@ -32,7 +32,7 @@
 import ShapeGroup from "./group.vue";
 import TempShapeGroup from "./draw-group.vue";
 import { DrawData, ShapeType, components } from "../components";
-import { useCursor, useMode, useStage } from "../hook/use-global-vars.ts";
+import { useCursor, useDownKeys, useMode, useStage } from "../hook/use-global-vars.ts";
 import { useViewerTransformConfig } from "../hook/use-viewer.ts";
 import { useListener, useResize } from "../hook/use-event.ts";
 import { useExpose } from "../hook/use-expose.ts";
@@ -40,9 +40,10 @@ import { DomMountId } from "../../constant";
 import ActiveBoxs from "../helper/active-boxs.vue";
 import SnapLines from "../helper/snap-lines.vue";
 import { useStore } from "../store/index.ts";
-import { useInteractiveAddShapeAPI } from "../hook/use-add.ts";
+import { useInteractiveDrawShapeAPI } from "../hook/use-draw.ts";
 import { Mode } from "@/constant/mode.ts";
-import { computed } from "vue";
+import { computed, watchEffect } from "vue";
+import { useMouseShapesStatus } from "../hook/use-mouse-status.ts";
 
 const props = defineProps<{
   data: DrawData;
@@ -57,12 +58,12 @@ const types = Object.keys(components) as ShapeType[];
 const mode = useMode();
 
 // 退出添加模式
-const { quitMouseAddShape } = useInteractiveAddShapeAPI();
+const { quitDrawShape } = useInteractiveDrawShapeAPI();
 useListener(
   "contextmenu",
   (ev) => {
     if (ev.button === 2) {
-      quitMouseAddShape();
+      quitDrawShape();
     }
   },
   document.documentElement
@@ -77,6 +78,25 @@ const cursorStyle = computed(() => {
   }
 });
 
+const status = useMouseShapesStatus();
+const downKeys = useDownKeys();
+
+watchEffect((onCleanup) => {
+  let style: string | null = null;
+  if (downKeys.has(" ")) {
+    style = "pointer";
+  } else if (mode.include(Mode.update)) {
+    style = "move";
+  } else if (status.hovers.length) {
+    style = "pointer";
+  }
+
+  if (style) {
+    cursor.push(style);
+    onCleanup(() => cursor.pop());
+  }
+});
+
 defineExpose(useExpose());
 </script>
 
@@ -87,6 +107,7 @@ defineExpose(useExpose());
   overflow: hidden;
   position: relative;
 }
+
 .mount-mask {
   position: absolute;
   inset: 0;

+ 1 - 0
src/core/store/index.ts

@@ -17,6 +17,7 @@ export const useStore = installGlobalVar(() => {
   ];
   store.$onAction(({ args, name, after, store }) => {
     if (!trackActions.includes(name)) return;
+    console.log(name, args)
     const isInit = name === "setStore";
     after(() => {
       if (isInit) {

+ 3 - 2
src/example/fuse/views/header/header.vue

@@ -83,8 +83,9 @@ const setBGImage = (file: File) => {
   draw.addShape(
     "image",
     {
-      width: 1000,
-      height: 1000,
+      width: window.innerWidth,
+      height: window.innerHeight,
+      listening: false,
       url: URL.createObjectURL(file),
       zIndex: -1,
     },

+ 477 - 64
src/example/fuse/views/init.ts

@@ -10,6 +10,18 @@ const initData = {
         243.9711189430529,
       ],
     },
+    {
+      id: "10cc6b4d-e90a-47c2-ae3f-9ab3a21190e7",
+      createTime: 1736762304345,
+      zIndex: -1,
+      opacity: 1,
+      ref: false,
+      width: 1000,
+      height: 1000,
+      listening: false,
+      url: "/五楼.png",
+      mat: [1, 0, 0, 1, 591, 436],
+    },
   ],
   rectangle: [
     {
@@ -32,16 +44,147 @@ const initData = {
       createTime: 0,
       zIndex: 0,
       attitude: [
-        1.2148907961465611, -1.1842248053033169, 0.9286933259554234,
-        0.9527422235147321, -403.84065282732183, 1441.7093493883922,
+        1.2148907961465611, -1.1842248053033169, 0.9286933259554236,
+        0.952742223514732, -274.21565282732183, 1472.5179431383922,
       ],
       fill: "red",
       points: [
-        { x: 662.2040392640735, y: 673.3008526997271 },
-        { x: 856.8446856698328, y: 483.5732802091982 },
-        { x: 1021.2743397890409, y: 652.260908190292 },
-        { x: 826.633693383281, y: 841.9884806808195 },
+        { x: 791.8290392640735, y: 704.1094464497272 },
+        { x: 986.4696856698326, y: 514.3818739591983 },
+        { x: 1150.8993397890408, y: 683.0695019402921 },
+        { x: 956.258693383281, y: 872.7970744308196 },
+      ],
+    },
+    {
+      id: "efe1cf7c-74ec-4c62-a23e-f68ced234c6b",
+      createTime: 1736386331805,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      points: [
+        { x: -399.703125, y: 420.65234375 },
+        { x: -281.390625, y: 420.65234375 },
+        { x: -281.390625, y: 544.06640625 },
+        { x: -399.703125, y: 544.06640625 },
+      ],
+      attitude: [1, 0, 0, 1, 0, 0],
+      dash: [4.32, 25.68],
+    },
+    {
+      id: "ec71e6ac-7214-484a-aebf-d0ea3bd6cd32",
+      createTime: 1736386333439,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      points: [
+        { x: -281.390625, y: 544.06640625 },
+        { x: -154.1640625, y: 544.06640625 },
+        { x: -154.1640625, y: 671.86328125 },
+        { x: -281.390625, y: 671.86328125 },
+      ],
+      attitude: [1, 0, 0, 1, 0, 0],
+    },
+    {
+      id: "f54f8b3b-4f2e-4811-b5c3-f90a2fd9deb2",
+      createTime: 1736386335742,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      points: [
+        { x: -281.390625, y: 544.06640625 },
+        { x: -399.703125, y: 544.06640625 },
+        { x: -399.703125, y: 671.86328125 },
+        { x: -281.390625, y: 671.86328125 },
+      ],
+      attitude: [1, 0, 0, 1, 0, 0],
+    },
+    {
+      id: "647b6f0d-6cf3-46ef-be3f-efd7854e66b6",
+      createTime: 1736386338885,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      points: [
+        { x: -281.390625, y: 544.06640625 },
+        { x: -154.1640625, y: 544.06640625 },
+        { x: -154.1640625, y: 420.65234375 },
+        { x: -281.390625, y: 420.65234375 },
+      ],
+      attitude: [1, 0, 0, 1, 0, 0],
+      dash: [8.1, 21.9],
+    },
+    {
+      id: "63d8d8d6-9bfc-4756-b4d8-28fd78d75404",
+      createTime: 1736386349032,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      points: [
+        { x: -154.1640625, y: 420.65234375 },
+        { x: -399.703125, y: 420.65234375 },
+        { x: -399.703125, y: 357.41015625 },
+        { x: -154.1640625, y: 357.41015625 },
+      ],
+      attitude: [1, 0, 0, 1, 0, 0],
+      dash: [19.81, 10.190000000000001],
+    },
+    {
+      id: "c147512f-b7fa-4638-83e9-b2bbd7311a4a",
+      createTime: 1736386356941,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      points: [
+        { x: -154.1640625, y: 671.86328125 },
+        { x: 70.11328125, y: 671.86328125 },
+        { x: 70.11328125, y: 357.41015625 },
+        { x: -154.1640625, y: 357.41015625 },
+      ],
+      attitude: [1, 0, 0, 1, 0, 0],
+    },
+    {
+      id: "27df2ef6-0d23-4620-be4c-c9ab49f6e46a",
+      createTime: 1736386360999,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      points: [
+        { x: -154.1640625, y: 357.41015625 },
+        { x: 70.11328125, y: 357.41015625 },
+        { x: 70.11328125, y: 544.06640625 },
+        { x: -154.1640625, y: 544.06640625 },
       ],
+      attitude: [1, 0, 0, 1, 0, 0],
+      dash: [3.63, 26.37],
+    },
+    {
+      id: "60dbebbb-f670-4279-aa5a-7686c366b121",
+      createTime: 1736386369847,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      points: [
+        { x: -154.1640625, y: 544.06640625 },
+        { x: 70.11328125, y: 544.06640625 },
+        { x: 70.11328125, y: 671.86328125 },
+        { x: -154.1640625, y: 671.86328125 },
+      ],
+      attitude: [1, 0, 0, 1, 0, 0],
+      dash: [5.72, 24.28],
+    },
+    {
+      id: "15d1acd3-66cf-4e76-bd92-ba2b8432f655",
+      createTime: 1736386395905,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      points: [
+        { x: -399.703125, y: 357.41015625 },
+        { x: -587.9070328715221, y: 357.41015625 },
+        { x: -587.9070328715221, y: 671.86328125 },
+        { x: -399.703125, y: 671.86328125 },
+      ],
+      attitude: [1, 0, 0, 1, 0, 0],
     },
   ],
   triangle: [
@@ -52,18 +195,69 @@ const initData = {
       id: "3",
       attitude: [1, 0, 0, 1, 0, 0],
       points: [
-        {
-          x: 115.58984375,
-          y: 626.625,
-        },
-        {
-          x: 229.76953125,
-          y: 495.828125,
-        },
-        {
-          x: 343.94921875,
-          y: 626.625,
-        },
+        { x: 115.58984375, y: 626.625 },
+        { x: 229.76953125, y: 495.828125 },
+        { x: 343.94921875, y: 626.625 },
+      ],
+    },
+    {
+      id: "b84daf26-66e0-40eb-a35a-ff143da7839c",
+      createTime: 1736386807568,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      points: [
+        { x: -597.0415203321531, y: 81.39090892655346 },
+        { x: -566.6056692947864, y: 8.839100341674886 },
+        { x: -536.1698182574196, y: 81.39090892655346 },
+      ],
+    },
+    {
+      id: "cc755da7-7cdd-44b6-b4a1-e2a9b9abb97c",
+      createTime: 1736386808809,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      points: [
+        { x: -505.7339672200528, y: 8.839100341674886 },
+        { x: -536.1698182574196, y: 81.39090892655346 },
+        { x: -566.6056692947864, y: 8.839100341674886 },
+      ],
+    },
+    {
+      id: "4b2505ac-4e61-4c79-9053-7ce9c8ef9f29",
+      createTime: 1736386811452,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      points: [
+        { x: -475.29811618268604, y: 81.39090892655346 },
+        { x: -505.7339672200528, y: 8.839100341674886 },
+        { x: -536.1698182574196, y: 81.39090892655346 },
+      ],
+    },
+    {
+      id: "8a18d563-3e1e-4b68-8436-f37a5ee932b4",
+      createTime: 1736386825508,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      points: [
+        { x: -444.86226514531927, y: 8.839100341674886 },
+        { x: -475.29811618268604, y: 81.39090892655346 },
+        { x: -505.7339672200528, y: 8.839100341674886 },
+      ],
+    },
+    {
+      id: "e5d5cc39-2277-4b97-9270-ab06812e33cc",
+      createTime: 1736386828089,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      points: [
+        { x: -414.4264141079525, y: 81.39090892655346 },
+        { x: -444.86226514531927, y: 8.839100341674886 },
+        { x: -475.29811618268604, y: 81.39090892655346 },
       ],
     },
   ],
@@ -74,23 +268,12 @@ const initData = {
       id: "33",
       attitude: [1, 0, 0, 1, 0, 0],
       points: [
-        {
-          x: 416.5390625,
-          y: 354.78125,
-        },
-        {
-          x: 715.4765625,
-          y: 370.1796875,
-        },
-        {
-          x: 686.734375,
-          y: 538.16796875,
-        },
-        {
-          x: 400.56640625,
-          y: 531.5390625,
-        },
+        { x: 416.5390625, y: 354.78125 },
+        { x: 715.4765625, y: 370.1796875 },
+        { x: 686.734375, y: 538.16796875 },
+        { x: 400.56640625, y: 531.5390625 },
       ],
+      dash: [18.42, 11.579999999999998],
     },
   ],
   line: [
@@ -100,23 +283,13 @@ const initData = {
       id: "333",
       attitude: [1, 0, 0, 1, 0, 0],
       points: [
-        {
-          x: 327.5546875,
-          y: 71.54296875,
-        },
-        {
-          x: 623.5703125,
-          y: 74.07421875,
-        },
-        {
-          x: 602.90234375,
-          y: 228.5,
-        },
-        {
-          x: 311.03515625,
-          y: 263.71484375,
-        },
+        { x: 327.5546875, y: 71.54296875 },
+        { x: 623.5703125, y: 74.07421875 },
+        { x: 602.90234375, y: 228.5 },
+        { x: 311.03515625, y: 263.71484375 },
       ],
+      ref: false,
+      dash: [20.66, 9.34],
     },
   ],
   arrow: [
@@ -136,14 +309,8 @@ const initData = {
       zIndex: 0,
       attitude: [1, 0, 0, 1, 0, 0],
       points: [
-        {
-          x: 756.35546875,
-          y: 94.78125,
-        },
-        {
-          x: 879.94140625,
-          y: 265.87109375,
-        },
+        { x: 756.35546875, y: 94.78125 },
+        { x: 879.94140625, y: 265.87109375 },
       ],
     },
   ],
@@ -156,6 +323,86 @@ const initData = {
       y: 100.3671875,
       radius: 84.72265625,
     },
+    {
+      id: "9ec46814-ebd9-4b6c-9901-b849a774251b",
+      createTime: 1736386847950,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      x: -253.43698048101692,
+      y: 94.24162863444133,
+      radius: 42.92427036911795,
+    },
+    {
+      id: "bb13c3e5-ce7c-490d-9e32-6ba1d70312d2",
+      createTime: 1736386861123,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      x: -161.3880040008919,
+      y: 94.24162863444133,
+      radius: 49.12470611100707,
+    },
+    {
+      id: "7fc10a01-e211-46a7-b1ac-6f6d136b25e9",
+      createTime: 1736386863425,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      x: -31.04138198657529,
+      y: 94.24162863444133,
+      radius: 81.22191590330954,
+    },
+    {
+      id: "226232c5-c4fe-4281-af03-99877ccd419e",
+      createTime: 1736386866584,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      x: -334.346030360653,
+      y: 94.24162863444133,
+      radius: 37.98477951051814,
+    },
+    {
+      id: "844a8f6c-6b3b-4d1c-b428-8ae415705cb3",
+      createTime: 1736386871198,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      x: -393.4777088349078,
+      y: 94.24162863444133,
+      radius: 21.146898963736646,
+    },
+    {
+      id: "d8b9ddf4-c6e4-4dd9-97ea-90eac6287085",
+      createTime: 1736386872987,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      x: -429.7180232437324,
+      y: 94.24162863444133,
+      radius: 15.093415445087942,
+    },
+    {
+      id: "4dc506af-6117-4624-9d21-9ea41f1fb22a",
+      createTime: 1736386875178,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      x: -455.18342141302026,
+      y: 94.24162863444133,
+      radius: 10.371982724199938,
+    },
+    {
+      id: "9e6c4261-7203-49ee-b1b3-b65c8f54920a",
+      createTime: 1736386877298,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      x: 213.103145547459,
+      y: 83.86964591024139,
+      radius: 162.92261163072476,
+    },
   ],
   icon: [
     {
@@ -163,7 +410,7 @@ const initData = {
       zIndex: 0,
       id: "3333",
       url: "/icons/vue.svg",
-      mat: [1, 0, 0, 1, 791.984375, 464.45703125],
+      mat: [1, 0, 0, 1, 886.53125, 626.64453125],
     },
     {
       createTime: 3,
@@ -188,8 +435,176 @@ const initData = {
       height: 300,
       stroke: "red",
       strokeWidth: 1,
-      strokeScaleEnabled: true,
-      mat: [1, 0, 0, 1, 954.53515625, 519.8671875],
+      strokeScaleEnabled: false,
+      mat: [1, 0, 0, 1, 1136.17578125, 358.5625],
+    },
+    {
+      id: "4f8b863e-5383-42fd-90ca-f5a81596067a",
+      createTime: 1736387547990,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      url: "/icons/BedsideCupboard.svg",
+      width: 100,
+      height: 100,
+      fill: "#D8000A",
+      mat: [1, 0, 0, 1, 437.5234375, 658.4296875],
+    },
+    {
+      id: "a2ddcd2d-9592-471e-92b3-e48b782a8a47",
+      createTime: 1736387551582,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      url: "/icons/BedsideCupboard.svg",
+      width: 100,
+      height: 100,
+      fill: "#D8000A",
+      mat: [1, 0, 0, 1, 327.5546875, 753.9650050474779],
+    },
+    {
+      id: "ef830da7-1beb-45ea-a5e0-8e3157a67448",
+      createTime: 1736387573383,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      url: "/icons/BedsideCupboard.svg",
+      width: 100,
+      height: 100,
+      fill: "#D8000A",
+      mat: [1, 0, 0, 1, 236.0523615799741, 852.1172134327413],
+    },
+    {
+      id: "f7ea5a07-277f-4cf6-9695-3e663473d6e4",
+      createTime: 1736387575046,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      url: "/icons/BedsideCupboard.svg",
+      width: 100,
+      height: 100,
+      fill: "#D8000A",
+      mat: [1, 0, 0, 1, 146.53893976251993, 951.8078358643269],
+    },
+    {
+      id: "d6e1659b-6daf-43e3-8d2c-71b51ecaf276",
+      createTime: 1736387576793,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      url: "/icons/BedsideCupboard.svg",
+      width: 100,
+      height: 100,
+      fill: "#D8000A",
+      mat: [1, 0, 0, 1, 236.0523615799741, 1044.307590830524],
+    },
+    {
+      id: "5378c1a7-33cf-4046-916f-1fc9eed18bce",
+      createTime: 1736387684662,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      url: "/icons/BedsideCupboard.svg",
+      width: 100,
+      height: 100,
+      fill: "#D8000A",
+      mat: [1, 0, 0, 1, 74.29382176684794, 764.6078162356459],
+    },
+    {
+      id: "18d451f1-f4b9-45eb-9b4b-a9a172377326",
+      createTime: 1736387685958,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      url: "/icons/BedsideCupboard.svg",
+      width: 100,
+      height: 100,
+      fill: "#D8000A",
+      mat: [1, 0, 0, 1, 727.6701549443019, 814.6078162356459],
+    },
+    {
+      id: "bd0356ff-c34b-4113-b636-e06dfcc94a0e",
+      createTime: 1736387687182,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      url: "/icons/BedsideCupboard.svg",
+      width: 100,
+      height: 100,
+      fill: "#D8000A",
+      mat: [1, 0, 0, 1, -32.11090723514161, 898.8453337880115],
+    },
+    {
+      id: "50492ad3-368e-400b-8fdf-361ab2f6ab8e",
+      createTime: 1736387693389,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      url: "/icons/BedsideCupboard.svg",
+      width: 100,
+      height: 100,
+      fill: "#D8000A",
+      mat: [1, 0, 0, 1, -127.56995895453684, 992.9009433033709],
+    },
+    {
+      id: "866bac92-e66f-48b3-b78c-95241d8a58d9",
+      createTime: 1736387701592,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      url: "/icons/BedsideCupboard.svg",
+      width: 100,
+      height: 100,
+      fill: "#D8000A",
+      mat: [1, 0, 0, 1, -77.56995895453684, 1042.900943303371],
+    },
+    {
+      id: "2b3e195c-673d-450b-bb4d-72915a9191cd",
+      createTime: 1736387719710,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      url: "/icons/BedsideCupboard.svg",
+      width: 100,
+      height: 100,
+      fill: "#D8000A",
+      mat: [1, 0, 0, 1, -120.01109686059323, 1092.900943303371],
+    },
+    {
+      id: "55100276-b2a8-43db-8d95-6a6ca8e236bc",
+      createTime: 1736387721815,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      url: "/icons/BedsideCupboard.svg",
+      width: 100,
+      height: 100,
+      fill: "#D8000A",
+      mat: [1, 0, 0, 1, -127.56995895453684, 1192.284570669999],
+    },
+    {
+      id: "a6e203de-19d9-48cc-8f4e-55d066a0a193",
+      createTime: 1736387727326,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      url: "/icons/BedsideCupboard.svg",
+      width: 100,
+      height: 100,
+      fill: "#D8000A",
+      mat: [1, 0, 0, 1, -27.569958954536844, 1192.284570669999],
+    },
+    {
+      id: "236e830c-3d6b-4dae-bd53-bfb4021d9673",
+      createTime: 1736387730142,
+      zIndex: 0,
+      opacity: 1,
+      ref: false,
+      url: "/icons/BedsideCupboard.svg",
+      width: 100,
+      height: 100,
+      fill: "#D8000A",
+      mat: [1, 0, 0, 1, 74.29382176684794, 1192.284570669999],
     },
   ],
   text: [
@@ -213,8 +628,6 @@ const initData = {
       zIndex: 0,
       id: "3t3asd33",
       fill: "#000",
-      // "stroke": "red",
-      // "strokeWidth": 3,
       fontFamily: "Calibri",
       fontSize: 30,
       width: 300,
@@ -228,6 +641,6 @@ const dataStr = localStorage.getItem("draw-data");
 export const data = dataStr ? JSON.parse(dataStr) : initData;
 
 export const save = (data: any) => {
-  console.log(data)
+  console.log(data);
   localStorage.setItem("draw-data", JSON.stringify(data));
 };

+ 1 - 1
src/example/fuse/views/slide/slide.vue

@@ -23,7 +23,7 @@ const draw = useDraw();
 const selectHandler = (value: string) => {
   const item = getItem(value);
   if (!item || !item.payload) throw "无效菜单";
-  draw.enterMouseAddShape(item.payload.type, item.payload.preset);
+  draw.enterDrawShape(item.payload.type, item.payload.preset);
 };
 </script>
 /