From d783aaa23671b61b247af3b22e5df45ab7117785 Mon Sep 17 00:00:00 2001 From: Ting Lu Date: Tue, 15 Apr 2025 20:31:33 -0400 Subject: [PATCH 1/3] implementation of resize --- packages/element/src/resizeElements.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/element/src/resizeElements.ts b/packages/element/src/resizeElements.ts index 3ff405603..1f569b3e3 100644 --- a/packages/element/src/resizeElements.ts +++ b/packages/element/src/resizeElements.ts @@ -1378,8 +1378,21 @@ export const resizeMultipleElements = ( ); if (keepAspectRatio) { - scaleX = scale; - scaleY = scale; + // If the elements are in a group and shouldMaintainAspectRatio is true(meaning user is holding shift), + // we need to adjust the scaleX or scaleY based on the handleDirection + if(targetElements.some(item => isInGroup(item.latest)) && shouldMaintainAspectRatio) { + if(handleDirection.length === 1) { + if(handleDirection.includes("e") || handleDirection.includes("w")) { + scaleX = scale; + } else if (handleDirection.includes("n") || handleDirection.includes("s")) { + scaleY = scale; + } + } + } + else { + scaleX = scale; + scaleY = scale; + } } /** From 2ec50ca587b8cc254d39234562caea103271a94a Mon Sep 17 00:00:00 2001 From: Ting Lu Date: Tue, 22 Apr 2025 01:31:40 -0400 Subject: [PATCH 2/3] test case + consistent text scaling --- packages/element/src/resizeElements.ts | 14 ++- packages/element/tests/groupResize.test.tsx | 116 ++++++++++++++++++++ 2 files changed, 125 insertions(+), 5 deletions(-) create mode 100644 packages/element/tests/groupResize.test.tsx diff --git a/packages/element/src/resizeElements.ts b/packages/element/src/resizeElements.ts index 1f569b3e3..c3a724799 100644 --- a/packages/element/src/resizeElements.ts +++ b/packages/element/src/resizeElements.ts @@ -1503,11 +1503,15 @@ export const resizeMultipleElements = ( } if (isTextElement(orig)) { - const metrics = measureFontSizeFromWidth(orig, elementsMap, width); - if (!metrics) { - return; + if (!shouldMaintainAspectRatio) { + const metrics = measureFontSizeFromWidth(orig, elementsMap, width); + if (!metrics) { + return; + } + update.fontSize = metrics.size; + } else { + update.fontSize = orig.fontSize; } - update.fontSize = metrics.size; } const boundTextElement = originalElementsMap.get( @@ -1515,7 +1519,7 @@ export const resizeMultipleElements = ( ) as ExcalidrawTextElementWithContainer | undefined; if (boundTextElement) { - if (keepAspectRatio) { + if (keepAspectRatio && !shouldMaintainAspectRatio) { const newFontSize = boundTextElement.fontSize * scale; if (newFontSize < MIN_FONT_SIZE) { return; diff --git a/packages/element/tests/groupResize.test.tsx b/packages/element/tests/groupResize.test.tsx new file mode 100644 index 000000000..3349eced9 --- /dev/null +++ b/packages/element/tests/groupResize.test.tsx @@ -0,0 +1,116 @@ +import { API } from "@excalidraw/excalidraw/tests/helpers/api"; +import { UI, Keyboard, Pointer } from "@excalidraw/excalidraw/tests/helpers/ui"; +import { KEYS } from "@excalidraw/common"; +import { unmountComponent } from "@excalidraw/excalidraw/tests/test-utils"; +import { render } from "@excalidraw/excalidraw/tests/test-utils"; +import { Excalidraw } from "@excalidraw/excalidraw"; +const { h } = window; +const mouse = new Pointer("mouse"); + +unmountComponent(); + +describe("group resize", () => { + beforeEach(() => { + h.elements = []; + }); + + it("resizes group with locked aspect ratio using side handles", async () => { + await render(); + + UI.clickTool("rectangle"); + mouse.down(10, 10); + mouse.up(10, 10); + + UI.clickTool("rectangle"); + mouse.down(10, -10); + mouse.up(10, 10); + + UI.clickTool("rectangle"); + mouse.down(10, -10); + mouse.up(10, 10); + const end = mouse.getPosition(); + + mouse.reset(); + mouse.down(); + mouse.restorePosition(...end); + mouse.up(); + + expect(h.elements.length).toBe(3); + for (const element of h.elements) { + expect(element.groupIds.length).toBe(0); + expect(h.state.selectedElementIds[element.id]).toBe(true); + } + + Keyboard.withModifierKeys({ ctrl: true }, () => { + Keyboard.keyPress(KEYS.G); + }); + + for (const element of h.elements) { + expect(element.groupIds.length).toBe(1); + } + + mouse.select(h.elements[0]); + let originalWidth = h.elements[0].width; + let originalHeight = h.elements[0].height; + + UI.resize(h.elements[0], 'se', [50, 50], { shift: true }); + + expect(h.elements[0].width).toBe(originalWidth + 50); + expect(h.elements[0].height).toBe(originalHeight + 50); + + originalWidth = h.elements[0].width; + originalHeight = h.elements[0].height; + + UI.resize(h.elements[0], "nw", [-50, -50], { shift: true }); + + expect(h.elements[0].width).toBe(originalWidth - 50); + expect(h.elements[0].height).toBe(originalHeight - 50); + }); + + it("resizes group with locked aspect ratio using corner handles", async () => { + await render(); + + UI.clickTool("rectangle"); + mouse.down(10, 10); + mouse.up(10, 10); + + UI.clickTool("rectangle"); + mouse.down(10, -10); + mouse.up(10, 10); + + UI.clickTool("rectangle"); + mouse.down(10, -10); + mouse.up(10, 10); + const end = mouse.getPosition(); + + mouse.reset(); + mouse.down(); + mouse.restorePosition(...end); + mouse.up(); + + expect(h.elements.length).toBe(3); + for (const element of h.elements) { + expect(element.groupIds.length).toBe(0); + expect(h.state.selectedElementIds[element.id]).toBe(true); + } + + Keyboard.withModifierKeys({ ctrl: true }, () => { + Keyboard.keyPress(KEYS.G); + }); + + for (const element of h.elements) { + expect(element.groupIds.length).toBe(1); + } + + mouse.select(h.elements[0]); + + let originalWidth = h.elements[0].width; + let originalHeight = h.elements[0].height; + + UI.resize(h.elements[0], "se", [50, 50], { shift: true }); + + + expect(h.elements[0].width).toBe(originalWidth + 50); + expect(h.elements[0].height).toBe(originalHeight + 50); + }); +}); \ No newline at end of file From 3f3110ce71f3e4df75f9ea4c74389b85afac3736 Mon Sep 17 00:00:00 2001 From: Ting Lu Date: Fri, 25 Apr 2025 13:36:46 -0400 Subject: [PATCH 3/3] change to test file --- packages/element/tests/groupResize.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/element/tests/groupResize.test.tsx b/packages/element/tests/groupResize.test.tsx index 3349eced9..c3be95be1 100644 --- a/packages/element/tests/groupResize.test.tsx +++ b/packages/element/tests/groupResize.test.tsx @@ -61,7 +61,7 @@ describe("group resize", () => { originalWidth = h.elements[0].width; originalHeight = h.elements[0].height; - UI.resize(h.elements[0], "nw", [-50, -50], { shift: true }); + UI.resize(h.elements[0], "e", [50, 0], { shift: true }); expect(h.elements[0].width).toBe(originalWidth - 50); expect(h.elements[0].height).toBe(originalHeight - 50);