Bladeren bron

feat: 短线连接点优化

bill 2 maanden geleden
bovenliggende
commit
3e0b70b58d
2 gewijzigde bestanden met toevoegingen van 99 en 18 verwijderingen
  1. 25 15
      src/core/components/line/single-line.vue
  2. 74 3
      src/core/components/line/use-draw.ts

+ 25 - 15
src/core/components/line/single-line.vue

@@ -1,18 +1,31 @@
 <template>
   <EditLine
     :ref="(d: any) => shape = d?.shape"
-    :data="{ ...line, ...style }"
+    :data="{ ...line, ...style, lineJoin: 'miter' }"
     :opacity="isDrawIng ? 0.5 : 1"
     :points="points"
     :closed="false"
     :id="line.id"
     :disablePoint="!canEdit || mode.include(Mode.readonly)"
     :ndx="0"
-    @dragstart="dragstartLineHandler(points.map((item) => item.id))"
-    @update:line="dragLineHandler"
-    @dragend="dragendLineHandler"
+    @dragstart="emit('dragLineStart', props.line)"
+    @update:line="(ps) => emit('dragLine', props.line, ps)"
+    @dragend="emit('dragLineEnd', props.line)"
     @add-point="addPoint"
   />
+  <template v-if="joinLines">
+    <v-line
+      v-for="line in joinLines"
+      ref="line"
+      :config="{
+        strokeWidth: 20,
+        opacity: isDrawIng ? 0.5 : 1,
+        stroke: 'red',
+        points: flatPositions(line),
+        listening: false,
+      }"
+    />
+  </template>
 
   <SizeLine
     v-if="
@@ -31,7 +44,7 @@
     <EditPoint
       v-for="(point, ndx) in points"
       :key="point.id"
-      :opacity="1"
+      :opacity="0.1"
       :size="line.strokeWidth"
       :points="points"
       :drawIng="ndx === 0 && isDrawIng"
@@ -68,7 +81,7 @@
 <script lang="ts" setup>
 import { computed, ref } from "vue";
 import { getMouseStyle, getSnapInfos, LineData, shapeName } from "./index.ts";
-import { onlyId } from "@/utils/shared.ts";
+import { flatPositions, onlyId } from "@/utils/shared.ts";
 import EditLine from "../share/edit-line.vue";
 import { getVectorLine, lineCenter, lineLen, lineVector, Pos } from "@/utils/math.ts";
 import EditPoint from "../share/edit-point.vue";
@@ -88,6 +101,7 @@ import {
 } from "@/core/hook/use-mouse-status.ts";
 import { themeColor } from "@/constant";
 import { Vector2 } from "three";
+import { extendLinesOverlap } from "./use-draw.ts";
 
 const mode = useMode();
 
@@ -99,6 +113,8 @@ const props = defineProps<{
   dragPointIds?: string[];
 }>();
 
+const joinLines = extendLinesOverlap(props.data, props.line);
+
 const emit = defineEmits<{
   (e: "updatePoint", value: LineData["points"][number]): void;
   (e: "addPoint", value: LineData["points"][number]): void;
@@ -231,13 +247,7 @@ const dragendHandler = () => {
   snapInfos.forEach((item) => infos.remove(item));
 };
 
-const dragstartLineHandler = (eIds: string[]) => {
-  emit("dragLineStart", props.line);
-};
-const dragLineHandler = (ps: Pos[]) => {
-  emit("dragLine", props.line, ps);
-};
-const dragendLineHandler = () => {
-  emit("dragLineEnd", props.line);
-};
+// const padstart = computed(() => {
+//   props.line.
+// })
 </script>

+ 74 - 3
src/core/components/line/use-draw.ts

@@ -361,6 +361,65 @@ export const repPointRef = (
   return data;
 };
 
+const eloCacle = new WeakMap<LineData, string[]>();
+export const extendLinesOverlap = (
+  data: LineData,
+  line1: LineData["lines"][0],
+) => {
+  const line1PIds = [line1.a, line1.b];
+  const line2 = data.lines.find(
+    (item) =>
+      (item !== line1 && line1PIds.includes(item.a)) ||
+      line1PIds.includes(item.b)
+  );
+  if (!line2) return;
+  const overlap = Math.max(line1.strokeWidth, line2.strokeWidth)
+  let eloeds = eloCacle.get(data);
+  if (!eloCacle.has(data)) {
+    eloCacle.set(data, (eloeds = []));
+  }
+  const key = line1.id + "j" + line2.id;
+  if (eloeds!.includes(key)) {
+    return;
+  } else {
+    eloeds!.push(key);
+  }
+
+  // 获取线段点
+  const pts1 = [
+    data.points.find((item) => item.id === line1.a)!,
+    data.points.find((item) => item.id === line1.b)!,
+  ];
+  const pts2 = [
+    data.points.find((item) => item.id === line2.a)!,
+    data.points.find((item) => item.id === line2.b)!,
+  ];
+
+  // 计算重叠向量
+  const dx = pts2[0].x - pts1[1].x;
+  const dy = pts2[0].y - pts1[1].y;
+  const len = Math.sqrt(dx * dx + dy * dy);
+  if (len === 0) {
+    return;
+  }
+
+  // 延长线段1的终点
+  const line1End = {
+    x: pts1[1].x + (dx / len) * overlap,
+    y: pts1[1].y + (dy / len) * overlap,
+  };
+
+  // 延长线段2的起点
+  const line2Start = {
+    x: pts2[0].x - (dx / len) * overlap,
+    y: pts2[0].y - (dy / len) * overlap,
+  };
+  return [
+    [pts1[1], line1End],
+    // [line2Start, pts2[0]],
+  ];
+};
+
 export const deduplicateLines = (data: LineData) => {
   const seen = new Map<string, LineData["lines"][0]>();
   let isChange = false;
@@ -639,7 +698,11 @@ export const genMoveLineHandler = (
     }
   };
 
-  const getSnapRefPoint = (point: Pos, refPoints: Pos[], line: Pos[] | null) => {
+  const getSnapRefPoint = (
+    point: Pos,
+    refPoints: Pos[],
+    line: Pos[] | null
+  ) => {
     for (const refPoint of refPoints) {
       if (
         lineLen(refPoint, point) < snapConfig.snapOffset &&
@@ -666,14 +729,22 @@ export const genMoveLineHandler = (
     };
 
     if (refInfos[0]?.joinPoints) {
-      refPoint = getSnapRefPoint(points[0], refInfos[0]?.joinPoints, snapLines[0]);
+      refPoint = getSnapRefPoint(
+        points[0],
+        refInfos[0]?.joinPoints,
+        snapLines[0]
+      );
       if (refPoint) {
         ndx = 0;
         return useRefPoint();
       }
     }
     if (refInfos[1]?.joinPoints) {
-      refPoint = getSnapRefPoint(points[1], refInfos[1]?.joinPoints, snapLines[1]);
+      refPoint = getSnapRefPoint(
+        points[1],
+        refInfos[1]?.joinPoints,
+        snapLines[1]
+      );
       if (refPoint) {
         ndx = 1;
         return useRefPoint();