resize linear & freedraw

This commit is contained in:
Ryan Di 2024-06-04 19:34:17 +08:00
parent 09e249ae57
commit be65ac7f22
3 changed files with 63 additions and 57 deletions

View File

@ -3,6 +3,7 @@ import DragInput from "./DragInput";
import type { DragInputCallbackType } from "./DragInput"; import type { DragInputCallbackType } from "./DragInput";
import { getStepSizedValue, isPropertyEditable } from "./utils"; import { getStepSizedValue, isPropertyEditable } from "./utils";
import { mutateElement } from "../../element/mutateElement"; import { mutateElement } from "../../element/mutateElement";
import { rescalePointsInElement } from "../../element/resizeElements";
interface DimensionDragInputProps { interface DimensionDragInputProps {
property: "width" | "height"; property: "width" | "height";
@ -50,6 +51,28 @@ export const newOrigin = (
}; };
}; };
const getResizedUpdates = (
nextWidth: number,
nextHeight: number,
latestState: ExcalidrawElement,
stateAtStart: ExcalidrawElement,
) => {
return {
...newOrigin(
latestState.x,
latestState.y,
latestState.width,
latestState.height,
nextWidth,
nextHeight,
latestState.angle,
),
width: nextWidth,
height: nextHeight,
...rescalePointsInElement(stateAtStart, nextWidth, nextHeight, true),
};
};
const DimensionDragInput = ({ property, element }: DimensionDragInputProps) => { const DimensionDragInput = ({ property, element }: DimensionDragInputProps) => {
const handleDimensionChange: DragInputCallbackType = ( const handleDimensionChange: DragInputCallbackType = (
accumulatedChange, accumulatedChange,
@ -83,19 +106,10 @@ const DimensionDragInput = ({ property, element }: DimensionDragInputProps) => {
0, 0,
); );
mutateElement(element, { mutateElement(
...newOrigin( element,
element.x, getResizedUpdates(nextWidth, nextHeight, element, _stateAtStart),
element.y, );
element.width,
element.height,
nextWidth,
nextHeight,
element.angle,
),
width: nextWidth,
height: nextHeight,
});
return; return;
} }
const changeInWidth = property === "width" ? accumulatedChange : 0; const changeInWidth = property === "width" ? accumulatedChange : 0;
@ -127,19 +141,10 @@ const DimensionDragInput = ({ property, element }: DimensionDragInputProps) => {
} }
} }
mutateElement(element, { mutateElement(
width: nextWidth, element,
height: nextHeight, getResizedUpdates(nextWidth, nextHeight, element, _stateAtStart),
...newOrigin( );
_stateAtStart.x,
_stateAtStart.y,
_stateAtStart.width,
_stateAtStart.height,
nextWidth,
nextHeight,
_stateAtStart.angle,
),
});
} }
}; };

View File

@ -1,5 +1,6 @@
import { getCommonBounds } from "../../element"; import { getCommonBounds } from "../../element";
import { mutateElement } from "../../element/mutateElement"; import { mutateElement } from "../../element/mutateElement";
import { rescalePointsInElement } from "../../element/resizeElements";
import type { ExcalidrawElement } from "../../element/types"; import type { ExcalidrawElement } from "../../element/types";
import DragInput from "./DragInput"; import DragInput from "./DragInput";
import type { DragInputCallbackType } from "./DragInput"; import type { DragInputCallbackType } from "./DragInput";
@ -12,6 +13,28 @@ interface MultiDimensionProps {
const STEP_SIZE = 10; const STEP_SIZE = 10;
const getResizedUpdates = (
anchorX: number,
anchorY: number,
scale: number,
stateAtStart: ExcalidrawElement,
) => {
const offsetX = stateAtStart.x - anchorX;
const offsetY = stateAtStart.y - anchorY;
const nextWidth = stateAtStart.width * scale;
const nextHeight = stateAtStart.height * scale;
const x = anchorX + offsetX * scale;
const y = anchorY + offsetY * scale;
return {
width: nextWidth,
height: nextHeight,
x,
y,
...rescalePointsInElement(stateAtStart, nextWidth, nextHeight, false),
};
};
const MultiDimension = ({ property, elements }: MultiDimensionProps) => { const MultiDimension = ({ property, elements }: MultiDimensionProps) => {
const handleDimensionChange: DragInputCallbackType = ( const handleDimensionChange: DragInputCallbackType = (
accumulatedChange, accumulatedChange,
@ -43,21 +66,9 @@ const MultiDimension = ({ property, elements }: MultiDimensionProps) => {
// it should never happen that element and origElement are different // it should never happen that element and origElement are different
// but check just in case // but check just in case
if (element.id === origElement.id) { if (element.id === origElement.id) {
const offsetX = origElement.x - anchorX;
const offsetY = origElement.y - anchorY;
const nextWidth = origElement.width * scale;
const nextHeight = origElement.height * scale;
const x = anchorX + offsetX * scale;
const y = anchorY + offsetY * scale;
mutateElement( mutateElement(
element, element,
{ getResizedUpdates(anchorX, anchorY, scale, origElement),
width: nextWidth,
height: nextHeight,
x,
y,
},
i === stateAtStart.length - 1, i === stateAtStart.length - 1,
); );
} }
@ -105,23 +116,13 @@ const MultiDimension = ({ property, elements }: MultiDimensionProps) => {
const element = elements[i]; const element = elements[i];
const origElement = stateAtStart[i]; const origElement = stateAtStart[i];
const offsetX = origElement.x - anchorX; if (element.id === origElement.id) {
const offsetY = origElement.y - anchorY; mutateElement(
const nextWidth = origElement.width * scale; element,
const nextHeight = origElement.height * scale; getResizedUpdates(anchorX, anchorY, scale, origElement),
const x = anchorX + offsetX * scale; i === stateAtStart.length - 1,
const y = anchorY + offsetY * scale; );
}
mutateElement(
element,
{
width: nextWidth,
height: nextHeight,
x,
y,
},
i === stateAtStart.length - 1,
);
i++; i++;
} }
}; };

View File

@ -182,7 +182,7 @@ const rotateSingleElement = (
} }
}; };
const rescalePointsInElement = ( export const rescalePointsInElement = (
element: NonDeletedExcalidrawElement, element: NonDeletedExcalidrawElement,
width: number, width: number,
height: number, height: number,