浏览代码

fix: Incorrect point offsetting in LinearElementEditor.movePoints() (#8145)

The LinearElementEditor.movePoints() function incorrectly calculates the offset for local linear element points when multiple targetPoints are provided, one of those target points is index === 0 AND the other points are moved in the negative direction, and ending up with negative local coordinates.

Signed-off-by: Mark Tolmacs <[email protected]>
Márk Tolmács 1 年之前
父节点
当前提交
ba8c09d529

+ 5 - 2
packages/excalidraw/element/linearElementEditor.ts

@@ -1165,7 +1165,7 @@ export class LinearElementEditor {
     const nextPoints = points.map((point, idx) => {
       const selectedPointData = targetPoints.find((p) => p.index === idx);
       if (selectedPointData) {
-        if (selectedOriginPoint) {
+        if (selectedPointData.index === 0) {
           return point;
         }
 
@@ -1174,7 +1174,10 @@ export class LinearElementEditor {
         const deltaY =
           selectedPointData.point[1] - points[selectedPointData.index][1];
 
-        return [point[0] + deltaX, point[1] + deltaY] as const;
+        return [
+          point[0] + deltaX - offsetX,
+          point[1] + deltaY - offsetY,
+        ] as const;
       }
       return offsetX || offsetY
         ? ([point[0] - offsetX, point[1] - offsetY] as const)

+ 32 - 8
packages/excalidraw/tests/linearElementEditor.test.tsx

@@ -27,6 +27,7 @@ import * as textElementUtils from "../element/textElement";
 import { ROUNDNESS, VERTICAL_ALIGN } from "../constants";
 import { vi } from "vitest";
 import { arrayToMap } from "../utils";
+import React from "react";
 
 const renderInteractiveScene = vi.spyOn(
   InteractiveCanvas,
@@ -972,10 +973,10 @@ describe("Test Linear Elements", () => {
       ]);
       expect((h.elements[1] as ExcalidrawTextElementWithContainer).text)
         .toMatchInlineSnapshot(`
-        "Online whiteboard 
-        collaboration made 
-        easy"
-      `);
+          "Online whiteboard 
+          collaboration made 
+          easy"
+        `);
     });
 
     it("should bind text to arrow when clicked on arrow and enter pressed", async () => {
@@ -1006,10 +1007,10 @@ describe("Test Linear Elements", () => {
       ]);
       expect((h.elements[1] as ExcalidrawTextElementWithContainer).text)
         .toMatchInlineSnapshot(`
-        "Online whiteboard 
-        collaboration made 
-        easy"
-      `);
+          "Online whiteboard 
+          collaboration made 
+          easy"
+        `);
     });
 
     it("should not bind text to line when double clicked", async () => {
@@ -1349,4 +1350,27 @@ describe("Test Linear Elements", () => {
       expect(label.y).toBe(0);
     });
   });
+
+  describe("Test moving linear element points", () => {
+    it("should move the endpoint in the negative direction correctly when the start point is also moved in the positive direction", async () => {
+      const line = createThreePointerLinearElement("arrow");
+      const [origStartX, origStartY] = [line.x, line.y];
+
+      LinearElementEditor.movePoints(line, [
+        { index: 0, point: [line.points[0][0] + 10, line.points[0][1] + 10] },
+        {
+          index: line.points.length - 1,
+          point: [
+            line.points[line.points.length - 1][0] - 10,
+            line.points[line.points.length - 1][1] - 10,
+          ],
+        },
+      ]);
+      expect(line.x).toBe(origStartX + 10);
+      expect(line.y).toBe(origStartY + 10);
+
+      expect(line.points[line.points.length - 1][0]).toBe(20);
+      expect(line.points[line.points.length - 1][1]).toBe(-20);
+    });
+  });
 });