123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- import { updateBoundElements } from "./binding";
- import { getCommonBounds } from "./bounds";
- import { mutateElement } from "./mutateElement";
- import { getPerfectElementSize } from "./sizeHelpers";
- import { NonDeletedExcalidrawElement } from "./types";
- import { AppState, PointerDownState } from "../types";
- import { getBoundTextElement } from "./textElement";
- import { isSelectedViaGroup } from "../groups";
- export const dragSelectedElements = (
- pointerDownState: PointerDownState,
- selectedElements: NonDeletedExcalidrawElement[],
- pointerX: number,
- pointerY: number,
- lockDirection: boolean = false,
- distanceX: number = 0,
- distanceY: number = 0,
- appState: AppState,
- ) => {
- const [x1, y1] = getCommonBounds(selectedElements);
- const offset = { x: pointerX - x1, y: pointerY - y1 };
- selectedElements.forEach((element) => {
- updateElementCoords(
- lockDirection,
- distanceX,
- distanceY,
- pointerDownState,
- element,
- offset,
- );
- // 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 (
- // container isn't part of any group
- // (perf optim so we don't check `isSelectedViaGroup()` in every case)
- !element.groupIds.length ||
- // container is part of a group, but we're dragging the container directly
- (appState.editingGroupId && !isSelectedViaGroup(appState, element))
- ) {
- const textElement = getBoundTextElement(element);
- if (textElement) {
- updateElementCoords(
- lockDirection,
- distanceX,
- distanceY,
- pointerDownState,
- textElement,
- offset,
- );
- }
- }
- updateBoundElements(element, {
- simultaneouslyUpdated: selectedElements,
- });
- });
- };
- const updateElementCoords = (
- lockDirection: boolean,
- distanceX: number,
- distanceY: number,
- pointerDownState: PointerDownState,
- element: NonDeletedExcalidrawElement,
- offset: { x: number; y: number },
- ) => {
- let x: number;
- let y: number;
- if (lockDirection) {
- const lockX = lockDirection && distanceX < distanceY;
- const lockY = lockDirection && distanceX > distanceY;
- const original = pointerDownState.originalElements.get(element.id);
- x = lockX && original ? original.x : element.x + offset.x;
- y = lockY && original ? original.y : element.y + offset.y;
- } else {
- x = element.x + offset.x;
- y = element.y + offset.y;
- }
- mutateElement(element, {
- x,
- y,
- });
- };
- export const getDragOffsetXY = (
- selectedElements: NonDeletedExcalidrawElement[],
- x: number,
- y: number,
- ): [number, number] => {
- const [x1, y1] = getCommonBounds(selectedElements);
- return [x - x1, y - y1];
- };
- export const dragNewElement = (
- draggingElement: NonDeletedExcalidrawElement,
- elementType: AppState["activeTool"]["type"],
- originX: number,
- originY: number,
- x: number,
- y: number,
- width: number,
- height: number,
- shouldMaintainAspectRatio: boolean,
- shouldResizeFromCenter: boolean,
- /** whether to keep given aspect ratio when `isResizeWithSidesSameLength` is
- true */
- widthAspectRatio?: number | null,
- ) => {
- if (shouldMaintainAspectRatio) {
- if (widthAspectRatio) {
- height = width / widthAspectRatio;
- } else {
- ({ width, height } = getPerfectElementSize(
- elementType,
- width,
- y < originY ? -height : height,
- ));
- if (height < 0) {
- height = -height;
- }
- }
- }
- let newX = x < originX ? originX - width : originX;
- let newY = y < originY ? originY - height : originY;
- if (shouldResizeFromCenter) {
- width += width;
- height += height;
- newX = originX - width / 2;
- newY = originY - height / 2;
- }
- if (width !== 0 && height !== 0) {
- mutateElement(draggingElement, {
- x: newX,
- y: newY,
- width,
- height,
- });
- }
- };
|