mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-04-14 16:40:58 -04:00
Some checks failed
Auto release excalidraw next / Auto-release-excalidraw-next (push) Failing after 2m36s
Build Docker image / build-docker (push) Failing after 6s
Cancel previous runs / cancel (push) Failing after 1s
Publish Docker / publish-docker (push) Failing after 31s
New Sentry production release / sentry (push) Failing after 2m3s
77 lines
2.2 KiB
TypeScript
77 lines
2.2 KiB
TypeScript
import type Scene from "@excalidraw/excalidraw/scene/Scene";
|
|
|
|
import { updateBoundElements } from "./binding";
|
|
import { getCommonBoundingBox } from "./bounds";
|
|
import { mutateElement } from "./mutateElement";
|
|
import { getMaximumGroups } from "./groups";
|
|
|
|
import type { BoundingBox } from "./bounds";
|
|
import type { ElementsMap, ExcalidrawElement } from "./types";
|
|
|
|
export interface Alignment {
|
|
position: "start" | "center" | "end";
|
|
axis: "x" | "y";
|
|
}
|
|
|
|
export const alignElements = (
|
|
selectedElements: ExcalidrawElement[],
|
|
elementsMap: ElementsMap,
|
|
alignment: Alignment,
|
|
scene: Scene,
|
|
): ExcalidrawElement[] => {
|
|
const groups: ExcalidrawElement[][] = getMaximumGroups(
|
|
selectedElements,
|
|
elementsMap,
|
|
);
|
|
const selectionBoundingBox = getCommonBoundingBox(selectedElements);
|
|
|
|
return groups.flatMap((group) => {
|
|
const translation = calculateTranslation(
|
|
group,
|
|
selectionBoundingBox,
|
|
alignment,
|
|
);
|
|
return group.map((element) => {
|
|
// update element
|
|
const updatedEle = mutateElement(element, {
|
|
x: element.x + translation.x,
|
|
y: element.y + translation.y,
|
|
});
|
|
// update bound elements
|
|
updateBoundElements(element, scene.getNonDeletedElementsMap(), {
|
|
simultaneouslyUpdated: group,
|
|
});
|
|
return updatedEle;
|
|
});
|
|
});
|
|
};
|
|
|
|
const calculateTranslation = (
|
|
group: ExcalidrawElement[],
|
|
selectionBoundingBox: BoundingBox,
|
|
{ axis, position }: Alignment,
|
|
): { x: number; y: number } => {
|
|
const groupBoundingBox = getCommonBoundingBox(group);
|
|
|
|
const [min, max]: ["minX" | "minY", "maxX" | "maxY"] =
|
|
axis === "x" ? ["minX", "maxX"] : ["minY", "maxY"];
|
|
|
|
const noTranslation = { x: 0, y: 0 };
|
|
if (position === "start") {
|
|
return {
|
|
...noTranslation,
|
|
[axis]: selectionBoundingBox[min] - groupBoundingBox[min],
|
|
};
|
|
} else if (position === "end") {
|
|
return {
|
|
...noTranslation,
|
|
[axis]: selectionBoundingBox[max] - groupBoundingBox[max],
|
|
};
|
|
} // else if (position === "center") {
|
|
return {
|
|
...noTranslation,
|
|
[axis]:
|
|
(selectionBoundingBox[min] + selectionBoundingBox[max]) / 2 -
|
|
(groupBoundingBox[min] + groupBoundingBox[max]) / 2,
|
|
};
|
|
};
|