ソースを参照

fix: element relative position when dragging multiple elements on grid (#7107)

Co-authored-by: dwelle <[email protected]>
zsviczian 1 年間 前
コミット
f098789d16
1 ファイル変更39 行追加26 行削除
  1. 39 26
      src/element/dragElements.ts

+ 39 - 26
src/element/dragElements.ts

@@ -1,5 +1,5 @@
 import { updateBoundElements } from "./binding";
-import { getCommonBounds } from "./bounds";
+import { Bounds, getCommonBounds } from "./bounds";
 import { mutateElement } from "./mutateElement";
 import { getPerfectElementSize } from "./sizeHelpers";
 import { NonDeletedExcalidrawElement } from "./types";
@@ -41,14 +41,20 @@ export const dragSelectedElements = (
     elementsInFrames.forEach((element) => elementsToUpdate.add(element));
   }
 
+  const commonBounds = getCommonBounds(
+    Array.from(elementsToUpdate).map(
+      (el) => pointerDownState.originalElements.get(el.id) ?? el,
+    ),
+  );
+  const adjustedOffset = calculateOffset(
+    commonBounds,
+    offset,
+    snapOffset,
+    gridSize,
+  );
+
   elementsToUpdate.forEach((element) => {
-    updateElementCoords(
-      pointerDownState,
-      element,
-      offset,
-      snapOffset,
-      gridSize,
-    );
+    updateElementCoords(pointerDownState, element, adjustedOffset);
     // update coords of bound text only if we're dragging the container directly
     // (we don't drag the group that it's part of)
     if (
@@ -66,13 +72,7 @@ export const dragSelectedElements = (
         // updating its coords again
         (!textElement.frameId || !frames.includes(textElement.frameId))
       ) {
-        updateElementCoords(
-          pointerDownState,
-          textElement,
-          offset,
-          snapOffset,
-          gridSize,
-        );
+        updateElementCoords(pointerDownState, textElement, adjustedOffset);
       }
     }
     updateBoundElements(element, {
@@ -81,23 +81,20 @@ export const dragSelectedElements = (
   });
 };
 
-const updateElementCoords = (
-  pointerDownState: PointerDownState,
-  element: NonDeletedExcalidrawElement,
+const calculateOffset = (
+  commonBounds: Bounds,
   dragOffset: { x: number; y: number },
   snapOffset: { x: number; y: number },
   gridSize: AppState["gridSize"],
-) => {
-  const originalElement =
-    pointerDownState.originalElements.get(element.id) ?? element;
-
-  let nextX = originalElement.x + dragOffset.x + snapOffset.x;
-  let nextY = originalElement.y + dragOffset.y + snapOffset.y;
+): { x: number; y: number } => {
+  const [x, y] = commonBounds;
+  let nextX = x + dragOffset.x + snapOffset.x;
+  let nextY = y + dragOffset.y + snapOffset.y;
 
   if (snapOffset.x === 0 || snapOffset.y === 0) {
     const [nextGridX, nextGridY] = getGridPoint(
-      originalElement.x + dragOffset.x,
-      originalElement.y + dragOffset.y,
+      x + dragOffset.x,
+      y + dragOffset.y,
       gridSize,
     );
 
@@ -109,6 +106,22 @@ const updateElementCoords = (
       nextY = nextGridY;
     }
   }
+  return {
+    x: nextX - x,
+    y: nextY - y,
+  };
+};
+
+const updateElementCoords = (
+  pointerDownState: PointerDownState,
+  element: NonDeletedExcalidrawElement,
+  dragOffset: { x: number; y: number },
+) => {
+  const originalElement =
+    pointerDownState.originalElements.get(element.id) ?? element;
+
+  const nextX = originalElement.x + dragOffset.x;
+  const nextY = originalElement.y + dragOffset.y;
 
   mutateElement(element, {
     x: nextX,