mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
refactor: separate resizing logic from pointer (#8155)
* separate resizing logic for a single element * replace resize logic in stats * do not recompute width and height from points when they're already given * correctly update linear elements' position when resized * update snapshots * lint * simplify linear resizing logic * fix initial scale for aspect ratio * update tests for linear elements * test typo * separate pointer from resizing for multiple elements * lint and simplify * fix tests * lint * provide scene in param instead * type * refactor code * fix floating in tests * remove restrictions/checks on width & height * update pointer to dimension to prevent regression --------- Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
This commit is contained in:
parent
56fca30bd0
commit
107eae3916
7 changed files with 1130 additions and 743 deletions
|
@ -18,6 +18,8 @@ import { LinearElementEditor } from "../element/linearElementEditor";
|
|||
import { arrayToMap } from "../utils";
|
||||
import type { LocalPoint } from "../../math";
|
||||
import { pointFrom } from "../../math";
|
||||
import { resizeSingleElement } from "../element/resizeElements";
|
||||
import { getSizeFromPoints } from "../points";
|
||||
|
||||
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
|
||||
|
||||
|
@ -235,7 +237,7 @@ describe.each(["line", "freedraw"] as const)("%s element", (type) => {
|
|||
};
|
||||
|
||||
it("resizes", async () => {
|
||||
const element = UI.createElement(type, { points: points[type] });
|
||||
const element = UI.createElement("freedraw", { points: points.freedraw });
|
||||
const bounds = getBoundsFromPoints(element);
|
||||
|
||||
UI.resize(element, "ne", [30, -60]);
|
||||
|
@ -249,7 +251,7 @@ describe.each(["line", "freedraw"] as const)("%s element", (type) => {
|
|||
});
|
||||
|
||||
it("flips while resizing", async () => {
|
||||
const element = UI.createElement(type, { points: points[type] });
|
||||
const element = UI.createElement("freedraw", { points: points.freedraw });
|
||||
const bounds = getBoundsFromPoints(element);
|
||||
|
||||
UI.resize(element, "sw", [140, -80]);
|
||||
|
@ -263,7 +265,7 @@ describe.each(["line", "freedraw"] as const)("%s element", (type) => {
|
|||
});
|
||||
|
||||
it("resizes with locked aspect ratio", async () => {
|
||||
const element = UI.createElement(type, { points: points[type] });
|
||||
const element = UI.createElement("freedraw", { points: points.freedraw });
|
||||
const bounds = getBoundsFromPoints(element);
|
||||
|
||||
UI.resize(element, "ne", [30, -60], { shift: true });
|
||||
|
@ -280,7 +282,7 @@ describe.each(["line", "freedraw"] as const)("%s element", (type) => {
|
|||
});
|
||||
|
||||
it("resizes from center", async () => {
|
||||
const element = UI.createElement(type, { points: points[type] });
|
||||
const element = UI.createElement("freedraw", { points: points.freedraw });
|
||||
const bounds = getBoundsFromPoints(element);
|
||||
|
||||
UI.resize(element, "nw", [-20, -30], { alt: true });
|
||||
|
@ -294,6 +296,147 @@ describe.each(["line", "freedraw"] as const)("%s element", (type) => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("line element", () => {
|
||||
const points: LocalPoint[] = [
|
||||
pointFrom(0, 0),
|
||||
pointFrom(60, -20),
|
||||
pointFrom(20, 40),
|
||||
pointFrom(-40, 0),
|
||||
];
|
||||
|
||||
it("resizes", async () => {
|
||||
UI.createElement("line", { points });
|
||||
|
||||
const element = h.elements[0] as ExcalidrawLinearElement;
|
||||
|
||||
const {
|
||||
x: prevX,
|
||||
y: prevY,
|
||||
width: prevWidth,
|
||||
height: prevHeight,
|
||||
} = element;
|
||||
|
||||
const nextWidth = prevWidth + 30;
|
||||
const nextHeight = prevHeight + 30;
|
||||
|
||||
resizeSingleElement(
|
||||
nextWidth,
|
||||
nextHeight,
|
||||
element,
|
||||
element,
|
||||
h.app.scene.getNonDeletedElementsMap(),
|
||||
h.app.scene.getNonDeletedElementsMap(),
|
||||
"ne",
|
||||
);
|
||||
|
||||
expect(element.x).not.toBe(prevX);
|
||||
expect(element.y).not.toBe(prevY);
|
||||
|
||||
expect(element.width).toBe(nextWidth);
|
||||
expect(element.height).toBe(nextHeight);
|
||||
|
||||
expect(element.points[0]).toEqual([0, 0]);
|
||||
|
||||
const { width, height } = getSizeFromPoints(element.points);
|
||||
expect(width).toBe(element.width);
|
||||
expect(height).toBe(element.height);
|
||||
});
|
||||
|
||||
it("flips while resizing", async () => {
|
||||
UI.createElement("line", { points });
|
||||
const element = h.elements[0] as ExcalidrawLinearElement;
|
||||
|
||||
const {
|
||||
width: prevWidth,
|
||||
height: prevHeight,
|
||||
points: prevPoints,
|
||||
} = element;
|
||||
|
||||
const nextWidth = prevWidth * -1;
|
||||
const nextHeight = prevHeight * -1;
|
||||
|
||||
resizeSingleElement(
|
||||
nextWidth,
|
||||
nextHeight,
|
||||
element,
|
||||
element,
|
||||
h.app.scene.getNonDeletedElementsMap(),
|
||||
h.app.scene.getNonDeletedElementsMap(),
|
||||
"se",
|
||||
);
|
||||
|
||||
expect(element.width).toBe(prevWidth);
|
||||
expect(element.height).toBe(prevHeight);
|
||||
|
||||
element.points.forEach((point, idx) => {
|
||||
expect(point[0]).toBeCloseTo(prevPoints[idx][0] * -1);
|
||||
expect(point[1]).toBeCloseTo(prevPoints[idx][1] * -1);
|
||||
});
|
||||
});
|
||||
|
||||
it("resizes with locked aspect ratio", async () => {
|
||||
UI.createElement("line", { points });
|
||||
const element = h.elements[0] as ExcalidrawLinearElement;
|
||||
|
||||
const { width: prevWidth, height: prevHeight } = element;
|
||||
|
||||
UI.resize(element, "ne", [30, -60], { shift: true });
|
||||
|
||||
const scaleHeight = element.width / prevWidth;
|
||||
const scaleWidth = element.height / prevHeight;
|
||||
|
||||
expect(scaleHeight).toBeCloseTo(scaleWidth);
|
||||
});
|
||||
|
||||
it("resizes from center", async () => {
|
||||
UI.createElement("line", {
|
||||
points: [
|
||||
pointFrom(0, 0),
|
||||
pointFrom(338.05644048727373, -180.4761618151104),
|
||||
pointFrom(338.05644048727373, 180.4761618151104),
|
||||
pointFrom(-338.05644048727373, 180.4761618151104),
|
||||
pointFrom(-338.05644048727373, -180.4761618151104),
|
||||
],
|
||||
});
|
||||
const element = h.elements[0] as ExcalidrawLinearElement;
|
||||
|
||||
const {
|
||||
x: prevX,
|
||||
y: prevY,
|
||||
width: prevWidth,
|
||||
height: prevHeight,
|
||||
} = element;
|
||||
|
||||
const prevSmallestX = Math.min(...element.points.map((p) => p[0]));
|
||||
const prevBiggestX = Math.max(...element.points.map((p) => p[0]));
|
||||
|
||||
resizeSingleElement(
|
||||
prevWidth + 20,
|
||||
prevHeight,
|
||||
element,
|
||||
element,
|
||||
h.app.scene.getNonDeletedElementsMap(),
|
||||
h.app.scene.getNonDeletedElementsMap(),
|
||||
"e",
|
||||
{
|
||||
shouldResizeFromCenter: true,
|
||||
},
|
||||
);
|
||||
|
||||
expect(element.width).toBeCloseTo(prevWidth + 20);
|
||||
expect(element.height).toBeCloseTo(prevHeight);
|
||||
|
||||
expect(element.x).toBeCloseTo(prevX);
|
||||
expect(element.y).toBeCloseTo(prevY);
|
||||
|
||||
const smallestX = Math.min(...element.points.map((p) => p[0]));
|
||||
const biggestX = Math.max(...element.points.map((p) => p[0]));
|
||||
|
||||
expect(prevSmallestX - smallestX).toBeCloseTo(10);
|
||||
expect(biggestX - prevBiggestX).toBeCloseTo(10);
|
||||
});
|
||||
});
|
||||
|
||||
describe("arrow element", () => {
|
||||
it("resizes with a label", async () => {
|
||||
const arrow = UI.createElement("arrow", {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue