Selaa lähdekoodia

fix: 提供多选

bill 5 kuukautta sitten
vanhempi
commit
35f61b3639
33 muutettua tiedostoa jossa 227 lisäystä ja 115 poistoa
  1. 3 3
      src/core/components/arrow/index.ts
  2. 10 1
      src/core/components/arrow/temp-arrow.vue
  3. 1 0
      src/core/components/circle/index.ts
  4. 16 0
      src/core/components/circle/temp-circle.vue
  5. 1 0
      src/core/components/icon/index.ts
  6. 1 0
      src/core/components/image/index.ts
  7. 1 0
      src/core/components/line/index.ts
  8. 9 1
      src/core/components/line/temp-line.vue
  9. 1 0
      src/core/components/polygon/index.ts
  10. 9 3
      src/core/components/polygon/temp-polygon.vue
  11. 1 0
      src/core/components/rectangle/index.ts
  12. 11 1
      src/core/components/rectangle/temp-rectangle.vue
  13. 1 1
      src/core/components/serial/serial-group.vue
  14. 50 27
      src/core/components/share/size-line.vue
  15. 1 0
      src/core/components/table/index.ts
  16. 1 0
      src/core/components/text/index.ts
  17. 1 0
      src/core/components/triangle/index.ts
  18. 10 0
      src/core/components/triangle/temp-triangle.vue
  19. 6 5
      src/core/hook/use-alignment.ts
  20. 3 5
      src/core/hook/use-config.ts
  21. 7 9
      src/core/hook/use-draw.ts
  22. 3 3
      src/core/hook/use-expose.ts
  23. 14 1
      src/core/hook/use-global-vars.ts
  24. 22 36
      src/core/hook/use-mouse-status.ts
  25. 1 1
      src/core/hook/use-snap.ts
  26. 2 2
      src/core/hook/use-transformer.ts
  27. 1 4
      src/core/hook/use-viewer.ts
  28. 1 0
      src/core/renderer/draw-shape.vue
  29. 6 10
      src/example/fuse/views/home.vue
  30. 10 0
      src/example/fuse/views/req.ts
  31. 17 1
      src/example/fuse/views/slide/test-menu.ts
  32. 1 1
      src/example/fuse/views/test.ts
  33. 5 0
      src/utils/colors.ts

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

@@ -34,6 +34,7 @@ export const getMouseStyle = (data: ArrowData) => {
       strokeWidth,
     },
     hover: { fill: strokeStatus.hover },
+    select: { fill: strokeStatus.select },
     press: { fill: strokeStatus.press },
   };
 };
@@ -51,9 +52,8 @@ export const dataToConfig = (data: ArrowData): ArrowConfig => ({
   hitStrokeWidth: 20,
 });
 
-export const getSnapInfos = (data: ArrowData) => {
-  return generateSnapInfos(getSnapPoints(data), true, false);
-};
+export const getSnapInfos = (data: ArrowData) => 
+  generateSnapInfos(getSnapPoints(data), true, true, true);
 
 export const getSnapPoints = (data: ArrowData) => data.points;
 

+ 10 - 1
src/core/components/arrow/temp-arrow.vue

@@ -27,10 +27,18 @@
       @update="emit('update')"
       v-if="shape"
     />
+
+    <SizeLine
+      v-if="config.showComponentSize"
+      :points="data.points"
+      :strokeWidth="data.strokeWidth"
+      :stroke="data.fill"
+    />
   </v-group>
 </template>
 
 <script lang="ts" setup>
+import SizeLine from "../share/size-line.vue";
 import EditPolygon from "../share/edit-polygon.vue";
 import { ArrowData, defaultStyle, PointerPosition } from "./index.ts";
 import { DC } from "@/deconstruction.js";
@@ -40,6 +48,7 @@ import { Arrow } from "konva/lib/shapes/Arrow";
 import { Pos } from "@/utils/math.ts";
 import { LineConfig } from "konva/lib/shapes/Line";
 import { Group } from "konva/lib/Group";
+import { useConfig } from "@/core/hook/use-config.ts";
 
 const props = defineProps<{ data: ArrowData; canEdit?: boolean; addMode?: boolean }>();
 const emit = defineEmits<{
@@ -48,7 +57,7 @@ const emit = defineEmits<{
 }>();
 
 const shape = ref<DC<Group>>();
-
+const config = useConfig();
 const data = computed(() => ({ ...defaultStyle, ...props.data }));
 const hitFunc: LineConfig["hitFunc"] = (con, shape) => {
   con.beginPath();

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

@@ -35,6 +35,7 @@ export const getMouseStyle = (data: CircleData) => {
   return {
     default: { fill: fillStatus && fillStatus.pub, stroke: strokeStatus.pub, strokeWidth },
     hover: { fill: fillStatus && fillStatus.hover, stroke: strokeStatus.hover },
+    select: { fill: fillStatus && fillStatus.select, stroke: strokeStatus.select  },
     press: { fill: fillStatus && fillStatus.press, stroke: strokeStatus.press },
   };
 };

+ 16 - 0
src/core/components/circle/temp-circle.vue

@@ -16,16 +16,31 @@
       @update-text="(val) => emit('updateContent', val)"
       @update:is-edit="(val) => emit('update:isEdit', val)"
     />
+
+    <SizeLine
+      :config="matConfig"
+      v-if="config.showComponentSize"
+      :points="[
+        { x: 0, y: -data.radiusY },
+        { x: 0, y: 0 },
+        { x: data.radiusX, y: 0 },
+      ]"
+      :margin="0"
+      :strokeWidth="data.strokeWidth"
+      :stroke="data.fill"
+    />
   </v-group>
 </template>
 
 <script lang="ts" setup>
+import SizeLine from "../share/size-line.vue";
 import ShareText from "../share/text.vue";
 import { CircleData, defaultStyle } from "./index.ts";
 import { computed, ref } from "vue";
 import { DC } from "@/deconstruction.js";
 import { Circle } from "konva/lib/shapes/Circle";
 import { Transform } from "konva/lib/Util";
+import { useConfig } from "@/core/hook/use-config.ts";
 
 const props = defineProps<{ data: CircleData; addMode?: boolean; editer?: boolean }>();
 const emit = defineEmits<{
@@ -33,6 +48,7 @@ const emit = defineEmits<{
   (e: "update:isEdit", data: boolean): void;
 }>();
 
+const config = useConfig();
 const data = computed(() => ({ ...defaultStyle, ...props.data }));
 
 const matConfig = computed(() => {

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

@@ -47,6 +47,7 @@ export const getMouseStyle = (data: IconData) => {
       coverOpcatiy: data.coverOpcatiy || 0,
     },
     hover: { coverFill: fillStatus.hover, coverOpcatiy: hCoverOpcaoty },
+    select: { coverFill: fillStatus.select, coverOpcatiy: hCoverOpcaoty  },
     press: { coverFill: fillStatus.press, coverOpcatiy: hCoverOpcaoty },
   };
 };

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

@@ -27,6 +27,7 @@ export const getMouseStyle = (data: ImageData) => {
   return {
     default: { stroke: strokeStatus.pub },
     hover: { stroke: strokeStatus.hover },
+    select: { stroke: strokeStatus.select },
     press: { stroke: strokeStatus.press },
   };
 };

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

@@ -23,6 +23,7 @@ export const getMouseStyle = (data: LineData) => {
   return {
     default: { stroke: strokeStatus.pub, strokeWidth },
     hover: { stroke: strokeStatus.hover },
+    select: { stroke: strokeStatus.select },
     press: { stroke: strokeStatus.press },
   };
 };

+ 9 - 1
src/core/components/line/temp-line.vue

@@ -19,17 +19,25 @@
       @update="emit('update')"
       v-if="shape"
     />
+    <SizeLine
+      v-if="config.showComponentSize"
+      :points="data.points"
+      :strokeWidth="data.strokeWidth"
+      :stroke="data.stroke"
+    />
   </v-group>
 </template>
 
 <script lang="ts" setup>
 import EditPolygon from "../share/edit-polygon.vue";
+import SizeLine from "../share/size-line.vue";
 import { defaultStyle, LineData } from "./index.ts";
 import { flatPositions } from "@/utils/shared.ts";
 import { computed, ref } from "vue";
 import { DC } from "@/deconstruction.js";
 import { Line, LineConfig } from "konva/lib/shapes/Line";
 import { Pos } from "@/utils/math.ts";
+import { useConfig } from "@/core/hook/use-config.ts";
 
 const props = defineProps<{
   data: LineData;
@@ -42,7 +50,7 @@ const emit = defineEmits<{
 }>();
 
 const data = computed(() => ({ ...defaultStyle, ...props.data }));
-
+const config = useConfig();
 const hitFunc: LineConfig["hitFunc"] = (con, shape) => {
   con.beginPath();
   con.moveTo(data.value.points[0].x, data.value.points[0].y);

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

@@ -27,6 +27,7 @@ export const getMouseStyle = (data: PolygonData) => {
     },
     hover: { fill: fillStatus && fillStatus.hover, stroke: strokeStatus.hover },
     press: { fill: fillStatus && fillStatus.press, stroke: strokeStatus.press },
+    select: { fill: fillStatus && fillStatus.select, stroke: strokeStatus.select },
   };
 };
 

+ 9 - 3
src/core/components/polygon/temp-polygon.vue

@@ -22,7 +22,13 @@
       v-if="shape"
     />
     <!-- status.hover -->
-    <SizeLine :data="data"  closed />
+    <SizeLine
+      v-if="config.showComponentSize"
+      :points="data.points"
+      :strokeWidth="data.strokeWidth"
+      :stroke="data.stroke"
+      closed
+    />
   </v-group>
 </template>
 
@@ -35,7 +41,7 @@ import { computed, ref } from "vue";
 import { DC } from "@/deconstruction.js";
 import { Line } from "konva/lib/shapes/Line";
 import { Pos } from "@/utils/math.ts";
-import { useMouseShapeStatus } from "@/core/hook/use-mouse-status.ts";
+import { useConfig } from "@/core/hook/use-config.ts";
 const props = defineProps<{ data: PolygonData; canEdit?: boolean; addMode?: boolean }>();
 const emit = defineEmits<{
   (e: "update:position", data: { ndx: number; val: Pos }): void;
@@ -44,7 +50,7 @@ const emit = defineEmits<{
 
 const data = computed(() => ({ ...defaultStyle, ...props.data }));
 const shape = ref<DC<Line>>();
-const status = useMouseShapeStatus(computed(() => shape.value));
+const config = useConfig();
 
 defineExpose({
   get shape() {

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

@@ -28,6 +28,7 @@ export const getMouseStyle = (data: RectangleData) => {
     default: { fill: fillStatus && fillStatus.pub, stroke: strokeStatus.pub, strokeWidth },
     hover: { fill: fillStatus && fillStatus.hover, stroke: strokeStatus.hover },
     press: { fill: fillStatus && fillStatus.press, stroke: strokeStatus.press },
+    select: { fill: fillStatus && fillStatus.select, stroke: strokeStatus.select },
   };
 };
 

+ 11 - 1
src/core/components/rectangle/temp-rectangle.vue

@@ -18,10 +18,18 @@
       @update-text="(val) => emit('updateContent', val)"
       @update:is-edit="(val) => emit('update:isEdit', val)"
     />
+    <SizeLine
+      v-if="config.showComponentSize"
+      :points="data.points"
+      :strokeWidth="data.strokeWidth"
+      :stroke="data.stroke"
+      closed
+    />
   </v-group>
 </template>
 
 <script lang="ts" setup>
+import SizeLine from "../share/size-line.vue";
 import ShareText from "../share/text.vue";
 import { flatPositions } from "@/utils/shared.ts";
 import { defaultStyle, RectangleData } from "./index.ts";
@@ -30,13 +38,15 @@ import { DC } from "@/deconstruction.js";
 import { Line } from "konva/lib/shapes/Line";
 import { Transform } from "konva/lib/Util";
 import { MathUtils } from "three";
-import { zIndex } from "html2canvas/dist/types/css/property-descriptors/z-index";
+import { useConfig } from "@/core/hook/use-config.ts";
+
 const props = defineProps<{ data: RectangleData; addMode?: boolean; editer?: boolean }>();
 const emit = defineEmits<{
   (e: "updateContent", data: string): void;
   (e: "update:isEdit", data: boolean): void;
 }>();
 
+const config = useConfig();
 const data = computed(() => ({ ...defaultStyle, ...props.data }));
 const textBound = computed(() => {
   const dec = new Transform(props.data.attitude).decompose();

+ 1 - 1
src/core/components/serial/serial-group.vue

@@ -40,8 +40,8 @@ const delHandler = (ndx: number) => {
     const c = (Number(data.value[i].content) - 1).toString();
     table.content[i + 1][0].content = data.value[i].content = c.toString();
   }
-  table.content.splice(ndx + 1, 1);
   table.height -= table.content[ndx + 1][0].height;
+  table.content.splice(ndx + 1, 1);
 
   history.onceTrack(() => {
     if (data.value.length === 1) {

+ 50 - 27
src/core/components/share/size-line.vue

@@ -4,14 +4,14 @@
       <v-line
         v-for="p in line.points"
         :config="{
-          stroke: stroke,
-          strokeWidth: strokeWidth,
+          stroke: style.stroke,
+          strokeWidth: style.strokeWidth / 2,
           points: flatPositions(p),
         }"
       />
       <v-textPath
         :config="{
-          fill: stroke,
+          fill: style.stroke,
           align: 'center',
           fontSize,
           textBaseline: 'middle',
@@ -24,7 +24,6 @@
 
 <script lang="ts" setup>
 import { computed } from "vue";
-import { LineData } from "../line";
 import {
   getPolygonDirection,
   getVectorLine,
@@ -40,53 +39,77 @@ import { TextPathConfig } from "konva/lib/shapes/TextPath";
 
 const props = withDefaults(
   defineProps<{
-    data: Required<Pick<LineData, "points" | "strokeWidth">>;
+    points: Pos[];
     stroke?: string;
     strokeWidth?: number;
     closed?: boolean;
+    margin?: number;
   }>(),
   { stroke: "#999", strokeWidth: 1 }
 );
 
-const fontSize = computed(() => 10 + props.strokeWidth * 2);
+const style = computed(() => ({ stroke: "#999", strokeWidth: 1 }));
+const fontSize = computed(() => 10 + style.value.strokeWidth * 2);
 const len = computed(() =>
-  props.closed ? props.data.points.length : props.data.points.length - 1
+  props.closed ? props.points.length : props.points.length - 1
 );
 const getLine = (ndx: number) =>
   [
-    props.data.points[ndx % props.data.points.length],
-    props.data.points[(ndx + 1) % props.data.points.length],
+    props.points[ndx % props.points.length],
+    props.points[(ndx + 1) % props.points.length],
   ] as [Pos, Pos];
-const isClockwise = computed(() => getPolygonDirection(props.data.points) <= 0);
+const isClockwise = computed(() => getPolygonDirection(props.points) <= 0);
 
 const proportion = useProportion();
-const margin = computed(() => -(props.data.strokeWidth + 10));
+const margin = computed(() =>
+  props.margin !== undefined ? props.margin! : -10 - style.value.strokeWidth * 2
+);
 const lines = computed(() => {
   const lines: { points: Pos[][]; textConfig: TextPathConfig }[] = [];
   for (let i = 0; i < len.value; i++) {
-    const line = getLine(i);
-    const lineOffset = isClockwise.value ? margin.value : -margin.value;
-    const vv = lineVerticalVector(line);
-    const offset = vv.multiplyScalar(lineOffset);
-    const p = [vector(line[0]).add(offset), vector(line[1]).add(offset)];
-    const text = proportion.transform(lineLen(...line));
-    const w = fontSize.value * text.length;
-    const lw = lineLen(p[0], p[1]);
-    if (w > lw) {
+    const baseLine = getLine(i).map(vector);
+    const baseLineVV = lineVerticalVector(baseLine);
+    const sizeMargin = isClockwise.value ? margin.value : -margin.value;
+    const sizeOffset = baseLineVV.clone().multiplyScalar(sizeMargin);
+    const sizeTextStr = proportion.transform(lineLen(baseLine[0], baseLine[1]));
+    const sizeTextW = (fontSize.value * sizeTextStr.length) / 1.5;
+    const baseLineW = lineLen(baseLine[0], baseLine[1]);
+
+    if (sizeTextW > baseLineW) {
       continue;
     }
-    const lv = lineVector(p);
-    const line1 = getVectorLine(lv, p[0], (lw - w) / 2);
-    const [_, start2] = getVectorLine(lv, line1[1], w);
-    const line2 = getVectorLine(lv, start2, (lw - w) / 2);
+
+    const sizeLine = [
+      baseLine[0].clone().add(sizeOffset),
+      baseLine[1].clone().add(sizeOffset),
+    ];
+    const sizeLineV = lineVector(baseLine);
+    const splitLineW = (baseLineW - sizeTextW) / 2;
+
+    const splitLine1 = getVectorLine(sizeLineV, sizeLine[0], splitLineW);
+    const [_, splitLine2Start] = getVectorLine(sizeLineV, splitLine1[1], sizeTextW);
+    const splitLine2 = getVectorLine(sizeLineV, splitLine2Start, splitLineW);
+
+    const padOffset1 = sizeOffset.clone().multiplyScalar(0.3);
+    const padOffset2 = sizeOffset.clone().multiplyScalar(-0.3);
+    const showLine1 = [
+      vector(splitLine1[0]).add(padOffset1),
+      vector(splitLine1[0]).add(padOffset2),
+      ...splitLine1,
+    ];
+    const showLine2 = [
+      ...splitLine2,
+      vector(splitLine2[1]).add(padOffset1),
+      vector(splitLine2[1]).add(padOffset2),
+    ];
 
     lines.push({
-      points: [line1, line2],
+      points: [showLine1, showLine2],
       textConfig: {
-        text: proportion.transform(lineLen(...line)),
+        text: sizeTextStr,
         x: 0,
         y: 0,
-        data: `M${p[0].x},${p[0].y} L${p[1].x},${p[1].y}`,
+        data: `M${sizeLine[0].x},${sizeLine[0].y} L${sizeLine[1].x},${sizeLine[1].y}`,
       },
     });
   }

+ 1 - 0
src/core/components/table/index.ts

@@ -53,6 +53,7 @@ export const getMouseStyle = (data: TableData) => {
     default: { stroke: strokeStatus.pub },
     hover: { stroke: strokeStatus.hover },
     press: { stroke: strokeStatus.press },
+    select: { select: strokeStatus.select },
   };
 };
 

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

@@ -44,6 +44,7 @@ export const getMouseStyle = (data: TextData) => {
     default: { fill: fillStatus.pub },
     hover: { fill: fillStatus.hover },
     press: { fill: fillStatus.press },
+    select: { select: fillStatus.select },
   };
 };
 

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

@@ -32,6 +32,7 @@ export const getMouseStyle = (data: TriangleData) => {
     },
     hover: { fill: fillStatus && fillStatus.hover, stroke: strokeStatus.hover },
     press: { fill: fillStatus && fillStatus.press, stroke: strokeStatus.press },
+    select: { select: fillStatus && fillStatus.select, stroke: strokeStatus.select },
   };
 };
 

+ 10 - 0
src/core/components/triangle/temp-triangle.vue

@@ -17,10 +17,18 @@
       @update-text="(val) => emit('updateContent', val)"
       @update:is-edit="(val) => emit('update:isEdit', val)"
     />
+    <SizeLine
+      v-if="config.showComponentSize"
+      :points="data.points"
+      :strokeWidth="data.strokeWidth"
+      :stroke="data.stroke"
+      closed
+    />
   </v-group>
 </template>
 
 <script lang="ts" setup>
+import SizeLine from "../share/size-line.vue";
 import ShareText from "../share/text.vue";
 import { DC } from "@/deconstruction.js";
 import { defaultStyle, TriangleData } from "./index.ts";
@@ -30,12 +38,14 @@ import { flatPositions } from "@/utils/shared.ts";
 import { Transform } from "konva/lib/Util";
 import { MathUtils } from "three";
 import { lineSpeed } from "@/utils/math.ts";
+import { useConfig } from "@/core/hook/use-config.ts";
 const props = defineProps<{ data: TriangleData; addMode?: boolean; editer?: boolean }>();
 const emit = defineEmits<{
   (e: "updateContent", data: string): void;
   (e: "update:isEdit", data: boolean): void;
 }>();
 const data = computed(() => ({ ...defaultStyle, ...props.data }));
+const config = useConfig();
 
 const shape = ref<DC<Line>>();
 const textBound = computed(() => {

+ 6 - 5
src/core/hook/use-alignment.ts

@@ -7,7 +7,7 @@ import {
   useTempLayer,
 } from "./use-layer";
 import { clickListener, listener } from "@/utils/event";
-import { useCursor, useDownKeys, useMode, useStage } from "./use-global-vars";
+import { useCursor, useOperMode, useMode, useStage } from "./use-global-vars";
 import { mergeFuns } from "@/utils/shared";
 import { getLineRelationMat, Pos } from "@/utils/math";
 import { Circle } from "konva/lib/shapes/Circle";
@@ -17,7 +17,7 @@ import { Shape } from "konva/lib/Shape";
 import { shapeTreeContain } from "@/utils/shape";
 import { useViewerInvertTransform, useViewerTransform } from "./use-viewer";
 import { Mode } from "@/constant/mode";
-import { useMouseShapesStatus, useMouseStyle } from "./use-mouse-status";
+import { useMouseShapesStatus } from "./use-mouse-status";
 
 export const useJoinShapes = (
   shapes: (Ref<DC<EntityShape> | undefined> | undefined)[]
@@ -112,7 +112,7 @@ export const useJoinShapes = (
 
   const mode = useMode()
   const cursor = useCursor();
-  const keys = useDownKeys();
+  const operMode = useOperMode()
   const status = useMouseShapesStatus()
   const select = async (sure: (ndx: number) => void) => {
     const $stage = stage.value!.getNode();
@@ -124,7 +124,7 @@ export const useJoinShapes = (
       const attrib = attribs[i];
       attrib.sticky && (attrib.sticky.value = true);
       const stopMove = listener(dom, "mousemove", () => {
-        if (attrib.canAdd() && !keys.has(" ")) {
+        if (attrib.canAdd() && !operMode.value.freeView) {
           points.value[i] = invertTransform.value.point($stage.pointerPos!);
         }
       });
@@ -134,8 +134,9 @@ export const useJoinShapes = (
       try {
         await new Promise<void>((resolve, reject) => {
           let isSure = false;
+          console.log(dom)
           const stopClick = clickListener(dom, () => {
-            if (!points.value[i] || keys.has(" ")) return;
+            if (!points.value[i] || operMode.value.freeView) return;
             stopMove();
             stopClick();
             sure(i);

+ 3 - 5
src/core/hook/use-config.ts

@@ -20,14 +20,15 @@ export type Config = {
   border?: Border | Border[];
   margin?: number | number[];
   showCompass: boolean
-
+  showComponentSize: boolean
 };
 
 export const defConfig: Config = {
   showGrid: true,
   showLabelLine: true,
   size: null,
-  showCompass: false
+  showCompass: false,
+  showComponentSize: true
 };
 
 export const useConfig = installGlobalVar(() => {
@@ -68,8 +69,5 @@ export const useConfig = installGlobalVar(() => {
         setFixSize(size)
       },
     }),
-    showCompass: false,
-    showGrid: true,
-    showLabelLine: true,
   }) as Config & StoreConfig;
 });

+ 7 - 9
src/core/hook/use-draw.ts

@@ -3,7 +3,7 @@ import {
   installGlobalVar,
   useCan,
   useCursor,
-  useDownKeys,
+  useOperMode,
   useMode,
   useStage,
 } from "./use-global-vars";
@@ -170,8 +170,7 @@ export const useDrawRunning = (shapeType?: ShapeType) => {
 };
 
 const usePointBeforeHandler = (enableTransform = false, enableSnap = false) => {
-  const downKeys = useDownKeys();
-  const free = computed(() => downKeys.has("Control"));
+  const operMode = useOperMode();
   const conversionPosition = useConversionPosition(enableTransform);
   const snap = enableSnap && useSnap();
   const infos = useCustomSnapInfos();
@@ -179,14 +178,14 @@ const usePointBeforeHandler = (enableTransform = false, enableSnap = false) => {
 
   return {
     transform: (p: SnapPoint, geo = [p], geoNeedConversion = true) => {
-      if (free.value) {
+      p = conversionPosition(p);
+      if (operMode.value.freeDraw) {
         return p
       }
       snap && snap.clear();
       if (geoNeedConversion) {
         geo = geo.map(conversionPosition);
       }
-      p = conversionPosition(p);
       const selfInfos = generateSnapInfos(geo, true, true);
       const transform = snap && snap.move(selfInfos);
       p = transform ? transform.point(p) : p;
@@ -444,8 +443,7 @@ export const useInteractiveDrawPen = <T extends ShapeType>(type: T) => {
   const processors = useStoreRenderProcessors();
   const store = useStore();
   const viewTransform = useViewerTransform();
-  const downKeys = useDownKeys();
-  const free = computed(() => downKeys.has("Control"));
+  const operMode = useOperMode();
   const processorIds = processors.register(() => {
     return (props: any) => h(DrawShape, { ...props, show: false });
   });
@@ -509,7 +507,7 @@ export const useInteractiveDrawPen = <T extends ShapeType>(type: T) => {
     let consumed = messages.value;
     currentCursor.value = penA;
     let pen: null | ReturnType<typeof penUpdatePoints> = null;
-    if (!free.value) {
+    if (!operMode.value.freeDraw) {
       pen = penUpdatePoints(messages.value, cur, type !== "polygon");
       consumed = pen.points;
       cur = pen.cur;
@@ -580,7 +578,7 @@ export const useInteractiveDrawPen = <T extends ShapeType>(type: T) => {
     };
 
     stopWatch = mergeFuns(
-      watch(free, update),
+      watch(() => operMode.value.freeDraw, update),
       watch(dot, update, { immediate: true, deep: true }),
       watch(
         messages,

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

@@ -1,10 +1,10 @@
 import {
   installGlobalVar,
   useCursor,
-  useDownKeys,
   useInstanceProps,
   useLayers,
   useMode,
+  useOperMode,
   useStage,
 } from "./use-global-vars.ts";
 import { Stage } from "konva/lib/Stage";
@@ -102,14 +102,14 @@ export const useAutoService = () => {
   useShortcutKey()
   // 鼠标自动变化服务
   const status = useMouseShapesStatus();
-  const downKeys = useDownKeys();
+  const operMode = useOperMode()
   const mode = useMode();
   const cursor = useCursor();
   const { set: setCursor } = cursor.push("initial");
 
   watchEffect(() => {
     let style: string | null = null;
-    if (downKeys.has(" ")) {
+    if (operMode.value.freeView) {
       style = "pointer";
     } else if (mode.include(Mode.update)) {
       style = "move";

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

@@ -46,7 +46,7 @@ export const installGlobalVar = <T>(
     if (!(key in instance)) {
       let val = create() as any;
       if (typeof val === "object" && "var" in val && "onDestroy" in val) {
-        val.onDestory && unmounteds.push(val.onDestory)
+        val.onDestroy && unmounteds.push(val.onDestroy)
         if (import.meta.env.DEV) {
           unmounteds.push(() => {
             console.log('销毁变量', key)
@@ -301,6 +301,19 @@ export const useDownKeys = installGlobalVar(() => {
   };
 });
 
+export const useOperMode = installGlobalVar(() => {
+  const keys = useDownKeys()
+
+  return computed(() => ({
+    // 多选模式
+    mulSelection: keys.has('Shift'),
+    // 自由移动视图
+    freeView: keys.has(' '),
+    // 自由绘图,不吸附
+    freeDraw: keys.has('Control')
+  }))
+})
+
 export const useLayers = () => {
   const stage = useStage();
   return computed(() => stage.value?.getNode().children as Layer[]);

+ 22 - 36
src/core/hook/use-mouse-status.ts

@@ -5,7 +5,7 @@ import {
   globalWatch,
   installGlobalVar,
   useCan,
-  useDownKeys,
+  useOperMode,
   useStage,
   useTransformIngShapes,
 } from "./use-global-vars.ts";
@@ -140,49 +140,25 @@ export const useMouseShapesStatus = installGlobalVar(() => {
   const press = ref([]) as Ref<EntityShape[]>;
   const selects = ref([]) as Ref<EntityShape[]>;
   const actives = ref([]) as Ref<EntityShape[]>;
-  const keys = useDownKeys();
-  const shapeIsTransformerInner = useShapeIsTransformerInner();
+  const operMode = useOperMode();
 
   const init = (stage: Stage) => {
     let downTarget: EntityShape | null;
 
-    const prevent = computed(() => keys.has(" "));
+    const prevent = computed(() => operMode.value.freeView);
     const [hover, hoverDestory] = getHoverShape(stage);
-    const hoverChange = (onCleanup: any) => {
+    const hoverChange = () => {
       if (prevent.value) {
         return;
       }
-
       hovers.value = hover.value
         ? shapeTreeContains(listeners.value, hover.value)
         : [];
-
-      // const pHover =
-      //   hover.value && shapeTreeContain(listeners.value, hover.value);
-
-      // // TODO首先确定之前的有没有离开
-      // if (hovers.value.length && hovers.value[0] !== pHover) {
-      //   hovers.value.pop();
-      //   console.log('omg?')
-      //   const check = hovers.value[0];
-      //   const [inner] = shapeIsTransformerInner(check);
-      //   onCleanup(
-      //     watchEffect(() => {
-      //       if (!inner.value && !prevent.value) {
-      //         hovers.value.pop();
-      //       }
-      //     })
-      //   );
-      // } else if (pHover) {
-      //   hovers.value[0] = pHover;
-      // } else if (hovers.value.length) {
-      //   hovers.value.pop();
-      // }
     };
 
     const stopHoverCheck = watch(
       () => [hover.value, prevent.value],
-      (_a, _b, onCleanup) => hoverChange(onCleanup)
+      hoverChange
     );
 
     let downTime: number;
@@ -193,10 +169,12 @@ export const useMouseShapesStatus = installGlobalVar(() => {
       if (target && !press.value.includes(target)) {
         press.value.push(target);
       }
+      if (!operMode.value.mulSelection)  {
+        selects.value = []
+      } 
       downTarget = target;
     });
 
-    let upCount = 0;
     return mergeFuns(
       stopHoverCheck,
       hoverDestory,
@@ -207,18 +185,26 @@ export const useMouseShapesStatus = installGlobalVar(() => {
           if (prevent.value) return;
           press.value = [];
           if (Date.now() - downTime > 300) return;
+          if (!downTarget || ev.button !== 0)  {
+            actives.value = []
+            selects.value = []
+            return;
+          }
 
-          if (downTarget && ev.button === 0) {
+          if (operMode.value.mulSelection)  {
             const ndx = selects.value.indexOf(downTarget);
             if (~ndx) {
               selects.value.splice(ndx, 1);
             } else {
               selects.value.push(downTarget);
             }
-            actives.value = [downTarget];
+            actives.value = []
+            
           } else {
-            actives.value = [];
+            actives.value = [downTarget];
+            selects.value = []
           }
+          console.log(selects.value)
         }
       ),
       () => {
@@ -376,9 +362,9 @@ export const useMouseStyle = <T extends ShapeType>(
     ) {
       styleMap.set(mouseStyle.value.drag, true);
     }
-    // if ('select' in props.style) {
-    // 	styleMap.set(props.style.select, status.value.select)
-    // }
+    if ('select' in mouseStyle.value) {
+      styleMap.set(mouseStyle.value.select, status.value.select);
+    }
 
     const finalStyle = {};
     for (const [style, use] of styleMap.entries()) {

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

@@ -127,7 +127,7 @@ export const useSnapConfig = () => {
   const unitTransform = useCacheUnitTransform();
   return {
     get snapOffset() {
-      return unitTransform.getPixel(10);
+      return unitTransform.getPixel(5);
     },
   };
 };

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

@@ -641,10 +641,10 @@ export const useMatCompTransformer = <T extends BaseItem & { mat: number[] }>(
     },
     handler(data, mat) {
       data.mat = mat.m;
-      return true
+      // return true
     },
     getRepShape: cloneRepShape,
     callback,
-    openSnap: true,
+    openSnap: false,
   });
 };

+ 1 - 4
src/core/hook/use-viewer.ts

@@ -1,15 +1,12 @@
 import { Viewer } from "../viewer.ts";
 import { computed, ref, watch } from "vue";
-import { dragListener, listener, scaleListener } from "../../utils/event.ts";
+import { dragListener, scaleListener } from "../../utils/event.ts";
 import {
   globalWatch,
   installGlobalVar,
   useCan,
-  useDownKeys,
-  useMode,
   useStage,
 } from "./use-global-vars.ts";
-import { Mode } from "../../constant/mode.ts";
 import { mergeFuns } from "../../utils/shared.ts";
 import { Transform } from "konva/lib/Util";
 import { lineLen } from "@/utils/math.ts";

+ 1 - 0
src/core/renderer/draw-shape.vue

@@ -24,6 +24,7 @@ watch(
   ({ canSnap, item }) => {
     infos.forEach(customSnapInfos.remove);
     if (!canSnap) return;
+    console.log("addSnap", item);
     infos = component.value.getSnapInfos(item as any);
     infos.forEach(customSnapInfos.add);
   },

+ 6 - 10
src/example/fuse/views/home.vue

@@ -10,12 +10,7 @@
     <div class="container">
       <Slide class="slide" v-if="draw" />
       <div class="content" ref="drawEle">
-        <DrawBoard
-          v-if="drawEle && show"
-          :handler-resource="uploadResourse"
-          ref="draw"
-          :data="data"
-        />
+        <DrawBoard v-if="drawEle && show" :handler-resource="uploadResourse" ref="draw" />
       </div>
     </div>
   </div>
@@ -31,16 +26,17 @@ import { installDraw } from "./use-draw.ts";
 import { listener } from "@/utils/event.ts";
 import { ElMessage } from "element-plus";
 import { startAnimation } from "@/utils/shared.ts";
-import { saveData, getData, uploadResourse } from "./req.ts";
-import { StoreData } from "@/core/store/store.ts";
+import { saveData, getData, uploadResourse, getViewport } from "./req.ts";
 
 const drawEle = ref<HTMLDivElement | null>(null);
 const draw = ref<DrawExpose>();
 installDraw(draw);
 
-const data = ref<StoreData>();
 const initData = async () => {
-  data.value = await getData();
+  const data = await getData();
+  const viewport = await getViewport();
+  draw.value?.store.repStore(data);
+  viewport && draw.value?.viewer.setViewMat(viewport);
 };
 initData();
 

+ 10 - 0
src/example/fuse/views/req.ts

@@ -10,6 +10,16 @@ export const saveData = async (data: StoreData) => {
   localStorage.setItem("draw-data", JSON.stringify(data));
 }
 
+
+export const getViewport = async () => {
+  const dataStr = localStorage.getItem("view-port");
+  return (dataStr ? JSON.parse(dataStr) : null) as number[] | null;
+}
+
+export const saveViewport = async (viewport: number[]) => {
+  localStorage.setItem("view-port", JSON.stringify(viewport));
+}
+
 export const uploadResourse = async (file: File) => {
   return URL.createObjectURL(file);
 };

+ 17 - 1
src/example/fuse/views/slide/test-menu.ts

@@ -1,7 +1,7 @@
 import { v4 as uuid } from "uuid";
 import { Draw } from "../use-draw";
-import { themeColor } from "@/constant/help-style";
 import { tInitData } from '../test'
+import { saveViewport } from "../req";
 
 export const testMenus = [
   {
@@ -35,6 +35,14 @@ export const testMenus = [
       {
         value: uuid(),
         icon: "",
+        name: "切换组件大小显示",
+        handler: (draw: Draw) => {
+          draw.config.showComponentSize = !draw.config.showComponentSize
+        }
+      },
+      {
+        value: uuid(),
+        icon: "",
         name: "碰撞检测",
         handler: (draw: Draw) => {
           draw.toggleHit()
@@ -48,6 +56,14 @@ export const testMenus = [
           draw.store.setStore(tInitData)
         }
       },
+      {
+        value: uuid(),
+        icon: "",
+        name: "设为视窗",
+        handler: (draw: Draw) => {
+          saveViewport(draw.viewer.transform.m)
+        }
+      },
     ],
   },
 ];

+ 1 - 1
src/example/fuse/views/test.ts

@@ -691,7 +691,7 @@ export const initData = {
     drawSize: null,
     compass: { rotation: 0 },
     proportion: {scale: 100, unit: 'mm'},
-  }
+  },
 };
 
 export const tInitData = {

+ 5 - 0
src/utils/colors.ts

@@ -21,6 +21,11 @@ const offset = {
     s: 0,
     l: -0.15,
   },
+  select: {
+    h: -0.0189,
+    s: 0,
+    l: -0.15,
+  },
 };
 type keys = keyof typeof offset;