浏览代码

fix: When moving a frame through the stats inputs or drags move along its children (#9433)

Co-authored-by: Mark Tolmacs <[email protected]>
Hazem Krimi 4 月之前
父节点
当前提交
6e655cdb24

+ 6 - 3
packages/excalidraw/components/Stats/MultiPosition.tsx

@@ -10,7 +10,12 @@ import type { ElementsMap, ExcalidrawElement } from "@excalidraw/element/types";
 import type Scene from "@excalidraw/element/Scene";
 
 import StatsDragInput from "./DragInput";
-import { getAtomicUnits, getStepSizedValue, isPropertyEditable } from "./utils";
+import {
+  getAtomicUnits,
+  getStepSizedValue,
+  isPropertyEditable,
+  STEP_SIZE,
+} from "./utils";
 import { getElementsInAtomicUnit, moveElement } from "./utils";
 
 import type { DragInputCallbackType } from "./DragInput";
@@ -26,8 +31,6 @@ interface MultiPositionProps {
   appState: AppState;
 }
 
-const STEP_SIZE = 10;
-
 const moveElements = (
   property: MultiPositionProps["property"],
   changeInTopX: number,

+ 1 - 3
packages/excalidraw/components/Stats/Position.tsx

@@ -11,7 +11,7 @@ import type { ElementsMap, ExcalidrawElement } from "@excalidraw/element/types";
 import type Scene from "@excalidraw/element/Scene";
 
 import StatsDragInput from "./DragInput";
-import { getStepSizedValue, moveElement } from "./utils";
+import { getStepSizedValue, moveElement, STEP_SIZE } from "./utils";
 
 import type { DragInputCallbackType } from "./DragInput";
 import type { AppState } from "../../types";
@@ -24,8 +24,6 @@ interface PositionProps {
   appState: AppState;
 }
 
-const STEP_SIZE = 10;
-
 const handlePositionChange: DragInputCallbackType<"x" | "y"> = ({
   accumulatedChange,
   instantChange,

+ 65 - 0
packages/excalidraw/components/Stats/utils.ts

@@ -12,6 +12,8 @@ import {
   isInGroup,
 } from "@excalidraw/element/groups";
 
+import { getFrameChildren } from "@excalidraw/element/frame";
+
 import type { Radians } from "@excalidraw/math";
 
 import type {
@@ -36,6 +38,7 @@ export type StatsInputProperty =
   | "gridStep";
 
 export const SMALLEST_DELTA = 0.01;
+export const STEP_SIZE = 10;
 
 export const isPropertyEditable = (
   element: ExcalidrawElement,
@@ -169,6 +172,68 @@ export const moveElement = (
         { informMutation: shouldInformMutation, isDragging: false },
       );
   }
+
+  if (isFrameLikeElement(originalElement)) {
+    const originalChildren = getFrameChildren(
+      originalElementsMap,
+      originalElement.id,
+    );
+    originalChildren.forEach((child) => {
+      const latestChildElement = elementsMap.get(child.id);
+
+      if (!latestChildElement) {
+        return;
+      }
+
+      const [childCX, childCY] = [
+        child.x + child.width / 2,
+        child.y + child.height / 2,
+      ];
+      const [childTopLeftX, childTopLeftY] = pointRotateRads(
+        pointFrom(child.x, child.y),
+        pointFrom(childCX, childCY),
+        child.angle,
+      );
+
+      const childNewTopLeftX = Math.round(childTopLeftX + changeInX);
+      const childNewTopLeftY = Math.round(childTopLeftY + changeInY);
+
+      const [childX, childY] = pointRotateRads(
+        pointFrom(childNewTopLeftX, childNewTopLeftY),
+        pointFrom(childCX + changeInX, childCY + changeInY),
+        -child.angle as Radians,
+      );
+
+      scene.mutateElement(
+        latestChildElement,
+        {
+          x: childX,
+          y: childY,
+        },
+        { informMutation: shouldInformMutation, isDragging: false },
+      );
+      updateBindings(latestChildElement, scene, {
+        simultaneouslyUpdated: originalChildren,
+      });
+
+      const boundTextElement = getBoundTextElement(
+        latestChildElement,
+        originalElementsMap,
+      );
+      if (boundTextElement) {
+        const latestBoundTextElement = elementsMap.get(boundTextElement.id);
+        latestBoundTextElement &&
+          scene.mutateElement(
+            latestBoundTextElement,
+            {
+              x: boundTextElement.x + changeInX,
+              y: boundTextElement.y + changeInY,
+            },
+            { informMutation: shouldInformMutation, isDragging: false },
+          );
+      }
+    });
+  }
 };
 
 export const getAtomicUnits = (