mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
Position revert
This commit is contained in:
parent
9a599cfc05
commit
5cc5c626df
4 changed files with 87 additions and 45 deletions
|
@ -18,10 +18,7 @@ import type { AppState } from "@excalidraw/excalidraw/types";
|
|||
|
||||
import type { Degrees, Radians } from "@excalidraw/math";
|
||||
|
||||
import type {
|
||||
ExcalidrawElement,
|
||||
NonDeletedExcalidrawElement,
|
||||
} from "@excalidraw/element/types";
|
||||
import type { ExcalidrawElement } from "@excalidraw/element/types";
|
||||
|
||||
import { angleIcon } from "../icons";
|
||||
|
||||
|
@ -75,14 +72,6 @@ const handleDegreeChange: DragInputCallbackType<AngleProps["property"]> = ({
|
|||
mutateElement(boundTextElement, { angle: nextAngle });
|
||||
}
|
||||
|
||||
setAppState({
|
||||
suggestedBindings: getSuggestedBindingsForArrows(
|
||||
[latestElement] as NonDeletedExcalidrawElement[],
|
||||
elementsMap,
|
||||
originalAppState.zoom,
|
||||
),
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -114,7 +103,7 @@ const handleDegreeChange: DragInputCallbackType<AngleProps["property"]> = ({
|
|||
|
||||
setAppState({
|
||||
suggestedBindings: getSuggestedBindingsForArrows(
|
||||
[latestElement] as NonDeletedExcalidrawElement[],
|
||||
[latestElement],
|
||||
elementsMap,
|
||||
originalAppState.zoom,
|
||||
),
|
||||
|
@ -122,7 +111,7 @@ const handleDegreeChange: DragInputCallbackType<AngleProps["property"]> = ({
|
|||
}
|
||||
};
|
||||
|
||||
const handleFinished: DragFinishedCallbackType = ({
|
||||
const handleFinished: DragFinishedCallbackType<AngleProps["property"]> = ({
|
||||
originalElements,
|
||||
originalAppState,
|
||||
scene,
|
||||
|
@ -137,25 +126,15 @@ const handleFinished: DragFinishedCallbackType = ({
|
|||
|
||||
if (latestElement) {
|
||||
updateBindings(latestElement, elementsMap, originalAppState.zoom, () => {
|
||||
const revertAngle = (latestElement.angle -
|
||||
degreesToRadians(accumulatedChange as Degrees)) as Radians;
|
||||
const change = degreesToRadians(accumulatedChange as Degrees);
|
||||
|
||||
mutateElement(latestElement, {
|
||||
angle: revertAngle,
|
||||
angle: (latestElement.angle - change) as Radians,
|
||||
});
|
||||
});
|
||||
|
||||
const boundTextElement = getBoundTextElement(
|
||||
latestElement,
|
||||
elementsMap,
|
||||
);
|
||||
|
||||
if (boundTextElement && !isArrowElement(latestElement)) {
|
||||
mutateElement(boundTextElement, { angle: revertAngle });
|
||||
}
|
||||
|
||||
setAppState({
|
||||
suggestedBindings: [],
|
||||
});
|
||||
setAppState({
|
||||
suggestedBindings: [],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,10 +37,14 @@ export type DragInputCallbackType<
|
|||
setAppState: React.Component<any, AppState>["setState"];
|
||||
}) => void;
|
||||
|
||||
export type DragFinishedCallbackType<E = ExcalidrawElement> = (props: {
|
||||
export type DragFinishedCallbackType<
|
||||
P extends StatsInputProperty,
|
||||
E = ExcalidrawElement,
|
||||
> = (props: {
|
||||
originalElements: readonly E[];
|
||||
originalElementsMap: ElementsMap;
|
||||
scene: Scene;
|
||||
property: P;
|
||||
originalAppState: AppState;
|
||||
accumulatedChange: number;
|
||||
setAppState: React.Component<any, AppState>["setState"];
|
||||
|
@ -57,7 +61,7 @@ interface StatsDragInputProps<
|
|||
editable?: boolean;
|
||||
shouldKeepAspectRatio?: boolean;
|
||||
dragInputCallback: DragInputCallbackType<T, E>;
|
||||
dragFinishedCallback?: DragFinishedCallbackType<E>;
|
||||
dragFinishedCallback?: DragFinishedCallbackType<T, E>;
|
||||
property: T;
|
||||
scene: Scene;
|
||||
appState: AppState;
|
||||
|
@ -136,6 +140,7 @@ const StatsDragInput = <
|
|||
// reason: idempotent to avoid unnecessary
|
||||
if (isNaN(original) || Math.abs(rounded - original) >= SMALLEST_DELTA) {
|
||||
stateRef.current.lastUpdatedValue = updatedValue;
|
||||
const originalElementsMap = app.scene.getNonDeletedElementsMap();
|
||||
dragInputCallback({
|
||||
accumulatedChange: 0,
|
||||
instantChange: 0,
|
||||
|
@ -150,6 +155,15 @@ const StatsDragInput = <
|
|||
setInputValue: (value) => setInputValue(String(value)),
|
||||
setAppState,
|
||||
});
|
||||
dragFinishedCallback?.({
|
||||
originalElements: elements,
|
||||
originalElementsMap,
|
||||
scene,
|
||||
originalAppState: appState,
|
||||
accumulatedChange: rounded,
|
||||
property,
|
||||
setAppState,
|
||||
});
|
||||
app.syncActionResult({
|
||||
captureUpdate: CaptureUpdateAction.IMMEDIATELY,
|
||||
});
|
||||
|
@ -303,6 +317,7 @@ const StatsDragInput = <
|
|||
originalElementsMap,
|
||||
scene,
|
||||
originalAppState,
|
||||
property,
|
||||
accumulatedChange,
|
||||
setAppState,
|
||||
});
|
||||
|
|
|
@ -7,12 +7,17 @@ import {
|
|||
import { mutateElement } from "@excalidraw/element/mutateElement";
|
||||
import { isImageElement } from "@excalidraw/element/typeChecks";
|
||||
|
||||
import { getSuggestedBindingsForArrows } from "@excalidraw/element/binding";
|
||||
|
||||
import type { ElementsMap, ExcalidrawElement } from "@excalidraw/element/types";
|
||||
|
||||
import StatsDragInput from "./DragInput";
|
||||
import { getStepSizedValue, moveElement } from "./utils";
|
||||
import { getStepSizedValue, moveElement, updateBindings } from "./utils";
|
||||
|
||||
import type { DragInputCallbackType } from "./DragInput";
|
||||
import type {
|
||||
DragFinishedCallbackType,
|
||||
DragInputCallbackType,
|
||||
} from "./DragInput";
|
||||
import type Scene from "../../scene/Scene";
|
||||
import type { AppState } from "../../types";
|
||||
|
||||
|
@ -36,6 +41,7 @@ const handlePositionChange: DragInputCallbackType<"x" | "y"> = ({
|
|||
property,
|
||||
scene,
|
||||
originalAppState,
|
||||
setAppState,
|
||||
}) => {
|
||||
const elementsMap = scene.getNonDeletedElementsMap();
|
||||
const origElement = originalElements[0];
|
||||
|
@ -122,6 +128,14 @@ const handlePositionChange: DragInputCallbackType<"x" | "y"> = ({
|
|||
crop: nextCrop,
|
||||
});
|
||||
|
||||
setAppState({
|
||||
suggestedBindings: getSuggestedBindingsForArrows(
|
||||
[origElement],
|
||||
elementsMap,
|
||||
originalAppState.zoom,
|
||||
),
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -135,6 +149,7 @@ const handlePositionChange: DragInputCallbackType<"x" | "y"> = ({
|
|||
elementsMap,
|
||||
originalElementsMap,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -166,15 +181,51 @@ const handlePositionChange: DragInputCallbackType<"x" | "y"> = ({
|
|||
elementsMap,
|
||||
originalElementsMap,
|
||||
);
|
||||
|
||||
if (origElement) {
|
||||
const latestElement = elementsMap.get(origElement.id);
|
||||
|
||||
if (latestElement) {
|
||||
setAppState({
|
||||
suggestedBindings: getSuggestedBindingsForArrows(
|
||||
[latestElement],
|
||||
elementsMap,
|
||||
originalAppState.zoom,
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const Position = ({
|
||||
property,
|
||||
element,
|
||||
elementsMap,
|
||||
const handleFinished: DragFinishedCallbackType<"x" | "y"> = ({
|
||||
originalElements,
|
||||
originalAppState,
|
||||
scene,
|
||||
appState,
|
||||
}: PositionProps) => {
|
||||
accumulatedChange,
|
||||
property,
|
||||
setAppState,
|
||||
}) => {
|
||||
const elementsMap = scene.getNonDeletedElementsMap();
|
||||
const origElement = originalElements[0];
|
||||
|
||||
if (origElement) {
|
||||
const latestElement = elementsMap.get(origElement.id);
|
||||
|
||||
if (latestElement) {
|
||||
updateBindings(latestElement, elementsMap, originalAppState.zoom, () => {
|
||||
mutateElement(latestElement, {
|
||||
[property]: latestElement[property] - accumulatedChange,
|
||||
});
|
||||
});
|
||||
|
||||
setAppState({
|
||||
suggestedBindings: [],
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const Position = ({ property, element, scene, appState }: PositionProps) => {
|
||||
const [topLeftX, topLeftY] = pointRotateRads(
|
||||
pointFrom(element.x, element.y),
|
||||
pointFrom(element.x + element.width / 2, element.y + element.height / 2),
|
||||
|
@ -202,6 +253,7 @@ const Position = ({
|
|||
label={property === "x" ? "X" : "Y"}
|
||||
elements={[element]}
|
||||
dragInputCallback={handlePositionChange}
|
||||
dragFinishedCallback={handleFinished}
|
||||
scene={scene}
|
||||
value={value}
|
||||
property={property}
|
||||
|
|
|
@ -204,7 +204,7 @@ export const updateBindings = (
|
|||
latestElement: ExcalidrawElement,
|
||||
elementsMap: NonDeletedSceneElementsMap,
|
||||
zoom?: AppState["zoom"],
|
||||
remainedBound?: () => void,
|
||||
bindingElementKeptOriginalBinding?: () => void,
|
||||
) => {
|
||||
if (isBindingElement(latestElement)) {
|
||||
const [start, end] = getOriginalBindingsIfStillCloseToArrowEnds(
|
||||
|
@ -217,7 +217,7 @@ export const updateBindings = (
|
|||
(latestElement.startBinding && start) ||
|
||||
(latestElement.endBinding && end)
|
||||
) {
|
||||
remainedBound?.();
|
||||
bindingElementKeptOriginalBinding?.();
|
||||
} else {
|
||||
if (latestElement.startBinding && !start) {
|
||||
unbindLinearElement(latestElement, "start");
|
||||
|
@ -227,9 +227,5 @@ export const updateBindings = (
|
|||
unbindLinearElement(latestElement, "end");
|
||||
}
|
||||
}
|
||||
|
||||
// else if (end) {
|
||||
// updateBoundElements(end, elementsMap);
|
||||
// }
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue