Browse Source

fix: 线段拖拽参考问题

bill 2 months ago
parent
commit
659a7abfb3
1 changed files with 89 additions and 39 deletions
  1. 89 39
      src/core/components/line/use-draw.ts

+ 89 - 39
src/core/components/line/use-draw.ts

@@ -17,9 +17,12 @@ import { copy, mergeFuns, onlyId, rangMod } from "@/utils/shared";
 import {
   eqPoint,
   getVectorLine,
+  lineIntersection,
+  lineLen,
   linePointProjection,
   lineVector,
   Pos,
+  vector,
   vector2IncludedAngle,
   verticalVector,
   zeroEq,
@@ -328,21 +331,26 @@ export const getInitCtx = (): NLineDataCtx => ({
   },
 });
 
-export const repPointRef = (data: LineData, delId: string, repId: string, queUpdate = true) => {
+export const repPointRef = (
+  data: LineData,
+  delId: string,
+  repId: string,
+  queUpdate = true
+) => {
   for (let i = 0; i < data.lines.length; i++) {
     const line = data.lines[i];
     if (line.a === delId) {
       if (queUpdate) {
         data.lines[i] = { ...line, a: repId };
       } else {
-        data.lines[i].a = repId
+        data.lines[i].a = repId;
       }
     }
     if (line.b === delId) {
       if (queUpdate) {
         data.lines[i] = { ...line, b: repId };
       } else {
-        data.lines[i].b = repId
+        data.lines[i].b = repId;
       }
     }
   }
@@ -423,11 +431,16 @@ export const normalLineData = (data: LineData, ctx: NLineDataCtx) => {
   return deduplicateLines(data);
 };
 
-export const genMoveLineHandler = (data: LineData, lineId: string, ctx = getInitCtx()) => {
+export const genMoveLineHandler = (
+  data: LineData,
+  lineId: string,
+  ctx = getInitCtx()
+) => {
   const line = data.lines.find((line) => line.id === lineId)!;
   const pointIds = [line.a, line.b];
   const points = pointIds.map((id) => data.points.find((p) => p.id === id)!);
-  const initPoints = copy(points)
+  const lineDire = lineVector(points)
+  const initPoints = copy(points);
   const angleRange = [MathUtils.degToRad(10), MathUtils.degToRad(170)];
   const getJoinLine = (pId: string) =>
     data.lines
@@ -505,67 +518,104 @@ export const genMoveLineHandler = (data: LineData, lineId: string, ctx = getInit
           angle: invAngle!,
         };
 
-    
-    info.angle = rangMod(info.angle, Math.PI)
-    const needVertical = info.angle > angleRange[1] || info.angle < angleRange[0];
-    const needSplit = needVertical || joinLineDires.some(
+    info.angle = rangMod(info.angle, Math.PI);
+    const needVertical =
+      info.angle > angleRange[1] || info.angle < angleRange[0];
+    const needSplit =
+      needVertical ||
+      joinLineDires.some(
         (dire) =>
           dire !== info.selectLineDire &&
           !zeroEq(
             rangMod(vector2IncludedAngle(dire, info.selectLineDire), Math.PI)
           )
-      )
-    return { ...info, needSplit, needVertical }
+      );
+    return { ...info, needSplit, needVertical };
   };
 
   let refInfos: ReturnType<typeof getRefInfo>[];
-  let snapLines: (null | Pos[])[]
-  let inited = false
+  let snapLines: (null | Pos[])[];
+  let inited = false;
 
   const init = (moveDires: Vector2[]) => {
-    refInfos = [getRefInfo(moveDires[0], 0), getRefInfo(moveDires[0], 1)]
-    snapLines = []
+    refInfos = [getRefInfo(moveDires[0], 0), getRefInfo(moveDires[0], 1)];
+    snapLines = [];
     for (let i = 0; i < refInfos.length; i++) {
-      const refInfo = refInfos[i]
+      const refInfo = refInfos[i];
       if (!refInfo) {
-        continue
+        continue;
       }
       if (refInfo.needSplit) {
         // 拆分点
-        const point = points[i]
-        const newPoint = { ...point, id: onlyId() }
-        data.points.push(newPoint)
-        repPointRef(data, point.id, newPoint.id, false)
-        const newLine = { ...getBaseItem(), ...defaultStyle, a: point.id, b: newPoint.id }
-        data.lines.push(newLine)
-        ctx.add.lines[newLine.id] = newLine
-        ctx.add.points[newPoint.id] = newPoint
+        const point = points[i];
+        const newPoint = { ...point, id: onlyId() };
+        data.points.push(newPoint);
+        repPointRef(data, point.id, newPoint.id, false);
+        const newLine = {
+          ...getBaseItem(),
+          ...defaultStyle,
+          a: point.id,
+          b: newPoint.id,
+        };
+        data.lines.push(newLine);
+        ctx.add.lines[newLine.id] = newLine;
+        ctx.add.points[newPoint.id] = newPoint;
 
         if (i) {
-          line.b = point.id
+          line.b = point.id;
         } else {
-          line.a = point.id
+          line.a = point.id;
         }
       }
-      const dire = refInfo.needVertical ? verticalVector(refInfo.selectLineDire) : refInfo.selectLineDire
-      snapLines[i] = getVectorLine(dire, copy(points[i]), 10)
+      const dire = refInfo.needVertical
+        ? verticalVector(refInfo.selectLineDire)
+        : refInfo.selectLineDire;
+      snapLines[i] = getVectorLine(dire, copy(points[i]), 10);
     }
+  };
+  const assignPos = (origin: LineData['points'][0], target: Pos) => {
+    origin.x = target.x
+    origin.y = target.y
+    ctx.update.points[origin.id] = origin
   }
 
   const handler = (finalPoss: Pos[]) => {
-    const moveDires = finalPoss.map((pos, ndx) => lineVector([initPoints[ndx], pos]))
     if (!inited) {
-      inited = true
-      init(moveDires)
+      const moveDires = finalPoss.map((pos, ndx) =>
+        lineVector([initPoints[ndx], pos])
+      );
+      inited = true;
+      init(moveDires);
+    }
+
+    if (!snapLines[0] && !snapLines[1]) {
+      assignPos(points[0], finalPoss[0])
+      assignPos(points[1], finalPoss[1])
+      return;
+    } else if (!snapLines[0]) {
+      const pos = linePointProjection(snapLines[1]!, finalPoss[1])
+      assignPos(points[1], pos)
+      assignPos(points[0], pos.sub(initPoints[1]).add(initPoints[0]))
+      return;
+    } else if (!snapLines[1]) {
+      const pos = linePointProjection(snapLines[0]!, finalPoss[0])
+      assignPos(points[0], pos)
+      assignPos(points[1], pos.sub(initPoints[0]).add(initPoints[1]))
+      return;
     }
-    
-    for (let i = 0; i < snapLines.length; i++) {
-      const snapLine = snapLines[i]
-      const fpos = !snapLine ? finalPoss[i] : linePointProjection(snapLine, finalPoss[i])
-      Object.assign(points[i], fpos)
-      ctx.update.points[points[i].id] = points[i]
+
+    const moves = snapLines.map((snapLine, i) => {
+      const pos = !snapLine ? finalPoss[i] : linePointProjection(snapLine, finalPoss[i])
+      return vector(pos).sub(initPoints[i])
+    });
+    if (moves[0].lengthSq() > moves[1].lengthSq()) {
+      assignPos(points[0], moves[0].add(initPoints[0]));
+      assignPos(points[1], lineIntersection(getVectorLine(lineDire, points[0]), snapLines[1])!)
+    } else {
+      assignPos(points[1], moves[1].add(initPoints[1]));
+      assignPos(points[0], lineIntersection(getVectorLine(lineDire, points[1]), snapLines[0])!)
     }
   };
 
-  return handler
+  return handler;
 };