2
0
Эх сурвалжийг харах

fix: #8475 Arrow updated on both sides (#8593)

Ritobroto Kalita 6 сар өмнө
parent
commit
c5d3bb0b6a

+ 26 - 2
packages/excalidraw/element/binding.ts

@@ -17,7 +17,11 @@ import type {
 } from "./types";
 
 import type { Bounds } from "./bounds";
-import { getCenterForBounds } from "./bounds";
+import {
+  getCenterForBounds,
+  getElementBounds,
+  doBoundsIntersect,
+} from "./bounds";
 import type { AppState } from "../types";
 import { isPointOnShape } from "@excalidraw/utils/collision";
 import {
@@ -743,6 +747,21 @@ export const updateBoundElements = (
       return;
     }
 
+    // Check for intersections before updating bound elements incase connected elements overlap
+    const startBindingElement = element.startBinding
+      ? elementsMap.get(element.startBinding.elementId)
+      : null;
+    const endBindingElement = element.endBinding
+      ? elementsMap.get(element.endBinding.elementId)
+      : null;
+
+    let startBounds: Bounds | null = null;
+    let endBounds: Bounds | null = null;
+    if (startBindingElement && endBindingElement) {
+      startBounds = getElementBounds(startBindingElement, elementsMap);
+      endBounds = getElementBounds(endBindingElement, elementsMap);
+    }
+
     const bindings = {
       startBinding: maybeCalculateNewGapWhenScaling(
         changedElement,
@@ -770,7 +789,12 @@ export const updateBoundElements = (
           bindableElement &&
           isBindableElement(bindableElement) &&
           (bindingProp === "startBinding" || bindingProp === "endBinding") &&
-          changedElement.id === element[bindingProp]?.elementId
+          (changedElement.id === element[bindingProp]?.elementId ||
+            (changedElement.id ===
+              element[
+                bindingProp === "startBinding" ? "endBinding" : "startBinding"
+              ]?.elementId &&
+              !doBoundsIntersect(startBounds, endBounds)))
         ) {
           const point = updateBoundPoint(
             element,

+ 14 - 0
packages/excalidraw/element/bounds.ts

@@ -1013,3 +1013,17 @@ export const getCenterForBounds = (bounds: Bounds): GlobalPoint =>
     bounds[0] + (bounds[2] - bounds[0]) / 2,
     bounds[1] + (bounds[3] - bounds[1]) / 2,
   );
+
+export const doBoundsIntersect = (
+  bounds1: Bounds | null,
+  bounds2: Bounds | null,
+): boolean => {
+  if (bounds1 == null || bounds2 == null) {
+    return false;
+  }
+
+  const [minX1, minY1, maxX1, maxY1] = bounds1;
+  const [minX2, minY2, maxX2, maxY2] = bounds2;
+
+  return minX1 < maxX2 && maxX1 > minX2 && minY1 < maxY2 && maxY1 > minY2;
+};

+ 3 - 1
packages/excalidraw/element/linearElementEditor.ts

@@ -219,7 +219,9 @@ export class LinearElementEditor {
     });
   }
 
-  /** @returns whether point was dragged */
+  /**
+   * @returns whether point was dragged
+   */
   static handlePointDragging(
     event: PointerEvent,
     app: AppClassProperties,

+ 25 - 25
packages/excalidraw/tests/__snapshots__/history.test.tsx.snap

@@ -297,7 +297,7 @@ History {
                 "focus": "0.00990",
                 "gap": 1,
               },
-              "height": "0.98597",
+              "height": "0.98586",
               "points": [
                 [
                   0,
@@ -305,7 +305,7 @@ History {
                 ],
                 [
                   "98.58579",
-                  "-0.98597",
+                  "-0.98586",
                 ],
               ],
               "startBinding": {
@@ -320,7 +320,7 @@ History {
                 "focus": "-0.02000",
                 "gap": 1,
               },
-              "height": "0.00119",
+              "height": "0.00000",
               "points": [
                 [
                   0,
@@ -328,7 +328,7 @@ History {
                 ],
                 [
                   "98.58579",
-                  "0.00119",
+                  "0.00000",
                 ],
               ],
               "startBinding": {
@@ -409,7 +409,7 @@ History {
                 "focus": "0.00990",
                 "gap": 1,
               },
-              "height": "0.98700",
+              "height": "0.98586",
               "points": [
                 [
                   0,
@@ -417,7 +417,7 @@ History {
                 ],
                 [
                   "98.58579",
-                  "-0.98700",
+                  "-0.98586",
                 ],
               ],
               "startBinding": {
@@ -425,7 +425,7 @@ History {
                 "focus": "0.02970",
                 "gap": 1,
               },
-              "y": "0.99465",
+              "y": "0.99364",
             },
           },
           "id175" => Delta {
@@ -1238,7 +1238,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
   "fillStyle": "solid",
   "frameId": null,
   "groupIds": [],
-  "height": "2.52823",
+  "height": "1.30038",
   "id": "id178",
   "index": "Zz",
   "isDeleted": false,
@@ -1253,7 +1253,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
     ],
     [
       "98.58579",
-      "-2.52823",
+      "1.30038",
     ],
   ],
   "roughness": 1,
@@ -1278,7 +1278,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
   "version": 11,
   "width": "98.58579",
   "x": "0.70711",
-  "y": "3.82861",
+  "y": 0,
 }
 `;
 
@@ -1609,7 +1609,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
   "fillStyle": "solid",
   "frameId": null,
   "groupIds": [],
-  "height": "2.52823",
+  "height": "1.30038",
   "id": "id181",
   "index": "a0",
   "isDeleted": false,
@@ -1624,7 +1624,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
     ],
     [
       "98.58579",
-      "-2.52823",
+      "1.30038",
     ],
   ],
   "roughness": 1,
@@ -1649,7 +1649,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
   "version": 11,
   "width": "98.58579",
   "x": "0.70711",
-  "y": "3.82861",
+  "y": 0,
 }
 `;
 
@@ -1767,7 +1767,7 @@ History {
               "fillStyle": "solid",
               "frameId": null,
               "groupIds": [],
-              "height": "22.07000",
+              "height": "11.27227",
               "index": "a0",
               "isDeleted": false,
               "lastCommittedPoint": null,
@@ -1780,8 +1780,8 @@ History {
                   0,
                 ],
                 [
-                  "99.27949",
-                  "-22.07000",
+                  "98.58579",
+                  "11.27227",
                 ],
               ],
               "roughness": 1,
@@ -1802,9 +1802,9 @@ History {
               "strokeStyle": "solid",
               "strokeWidth": 2,
               "type": "arrow",
-              "width": "99.27949",
-              "x": "0.01341",
-              "y": "33.34227",
+              "width": "98.58579",
+              "x": "0.70711",
+              "y": 0,
             },
             "inserted": {
               "isDeleted": true,
@@ -2320,7 +2320,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
   "fillStyle": "solid",
   "frameId": null,
   "groupIds": [],
-  "height": "410.63965",
+  "height": "374.05754",
   "id": "id186",
   "index": "a2",
   "isDeleted": false,
@@ -2334,8 +2334,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
       0,
     ],
     [
-      "501.24760",
-      "-410.63965",
+      "502.78936",
+      "-374.05754",
     ],
   ],
   "roughness": 1,
@@ -2354,9 +2354,9 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
   "type": "arrow",
   "updated": 1,
   "version": 10,
-  "width": "501.24760",
-  "x": "0.70711",
-  "y": 0,
+  "width": "502.78936",
+  "x": "-0.83465",
+  "y": "-36.58211",
 }
 `;
 

+ 6 - 6
packages/excalidraw/tests/__snapshots__/move.test.tsx.snap

@@ -196,7 +196,7 @@ exports[`move element > rectangles with binding arrow 7`] = `
   "fillStyle": "solid",
   "frameId": null,
   "groupIds": [],
-  "height": "84.41974",
+  "height": "87.29887",
   "id": "id2",
   "index": "a2",
   "isDeleted": false,
@@ -210,8 +210,8 @@ exports[`move element > rectangles with binding arrow 7`] = `
       0,
     ],
     [
-      "83.92893",
-      "84.41974",
+      "86.85786",
+      "87.29887",
     ],
   ],
   "roughness": 1,
@@ -232,8 +232,8 @@ exports[`move element > rectangles with binding arrow 7`] = `
   "updated": 1,
   "version": 11,
   "versionNonce": 1051383431,
-  "width": "83.92893",
-  "x": 110,
-  "y": 50,
+  "width": "86.85786",
+  "x": "107.07107",
+  "y": "47.07107",
 }
 `;

+ 3 - 4
packages/excalidraw/tests/move.test.tsx

@@ -1,4 +1,5 @@
 import React from "react";
+import "../../utils/test-utils";
 import { render, fireEvent, act, unmountComponent } from "./test-utils";
 import { Excalidraw } from "../index";
 import * as StaticScene from "../renderer/staticScene";
@@ -121,10 +122,8 @@ describe("move element", () => {
     expect(h.state.selectedElementIds[rectB.id]).toBeTruthy();
     expect([rectA.x, rectA.y]).toEqual([0, 0]);
     expect([rectB.x, rectB.y]).toEqual([201, 2]);
-    expect([Math.round(arrow.x), Math.round(arrow.y)]).toEqual([110, 50]);
-    expect([Math.round(arrow.width), Math.round(arrow.height)]).toEqual([
-      84, 84,
-    ]);
+    expect([[arrow.x, arrow.y]]).toCloselyEqualPoints([[107.07, 47.07]]);
+    expect([[arrow.width, arrow.height]]).toCloselyEqualPoints([[86.86, 87.3]]);
 
     h.elements.forEach((element) => expect(element).toMatchSnapshot());
   });