mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-11-15 02:04:21 +01:00
feat: Better restore for bindings
This commit is contained in:
@@ -18,7 +18,13 @@ import {
|
|||||||
normalizeLink,
|
normalizeLink,
|
||||||
getLineHeight,
|
getLineHeight,
|
||||||
} from "@excalidraw/common";
|
} from "@excalidraw/common";
|
||||||
import { getNonDeletedElements, isValidPolygon } from "@excalidraw/element";
|
import {
|
||||||
|
calculateFixedPointForNonElbowArrowBinding,
|
||||||
|
getNonDeletedElements,
|
||||||
|
isPointInElement,
|
||||||
|
isValidPolygon,
|
||||||
|
projectFixedPointOntoDiagonal,
|
||||||
|
} from "@excalidraw/element";
|
||||||
import { normalizeFixedPoint } from "@excalidraw/element";
|
import { normalizeFixedPoint } from "@excalidraw/element";
|
||||||
import {
|
import {
|
||||||
updateElbowArrowPoints,
|
updateElbowArrowPoints,
|
||||||
@@ -50,9 +56,9 @@ import type { LocalPoint, Radians } from "@excalidraw/math";
|
|||||||
|
|
||||||
import type {
|
import type {
|
||||||
ExcalidrawArrowElement,
|
ExcalidrawArrowElement,
|
||||||
|
ExcalidrawBindableElement,
|
||||||
ExcalidrawElbowArrowElement,
|
ExcalidrawElbowArrowElement,
|
||||||
ExcalidrawElement,
|
ExcalidrawElement,
|
||||||
ExcalidrawElementType,
|
|
||||||
ExcalidrawLinearElement,
|
ExcalidrawLinearElement,
|
||||||
ExcalidrawSelectionElement,
|
ExcalidrawSelectionElement,
|
||||||
ExcalidrawTextElement,
|
ExcalidrawTextElement,
|
||||||
@@ -119,9 +125,11 @@ const getFontFamilyByName = (fontFamilyName: string): FontFamilyValues => {
|
|||||||
return DEFAULT_FONT_FAMILY;
|
return DEFAULT_FONT_FAMILY;
|
||||||
};
|
};
|
||||||
|
|
||||||
const repairBinding = <T extends ExcalidrawLinearElement>(
|
const repairBinding = <T extends ExcalidrawArrowElement>(
|
||||||
element: T,
|
element: T,
|
||||||
binding: FixedPointBinding | null,
|
binding: FixedPointBinding | null,
|
||||||
|
elements: readonly ExcalidrawElement[],
|
||||||
|
startOrEnd: "start" | "end",
|
||||||
): FixedPointBinding | null => {
|
): FixedPointBinding | null => {
|
||||||
if (!binding) {
|
if (!binding) {
|
||||||
return null;
|
return null;
|
||||||
@@ -139,11 +147,54 @@ const repairBinding = <T extends ExcalidrawLinearElement>(
|
|||||||
return fixedPointBinding;
|
return fixedPointBinding;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
const boundElement =
|
||||||
elementId: binding.elementId,
|
(elements.find(
|
||||||
mode: binding.mode || "orbit",
|
(el) => el.id === binding.elementId,
|
||||||
fixedPoint: normalizeFixedPoint(binding.fixedPoint || [0.51, 0.51]),
|
) as ExcalidrawBindableElement) || undefined;
|
||||||
} as FixedPointBinding | null;
|
if (boundElement) {
|
||||||
|
if (binding.mode) {
|
||||||
|
return {
|
||||||
|
elementId: binding.elementId,
|
||||||
|
mode: binding.mode || "orbit",
|
||||||
|
fixedPoint: normalizeFixedPoint(binding.fixedPoint || [0.51, 0.51]),
|
||||||
|
} as FixedPointBinding | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const elementsMap = arrayToMap(elements);
|
||||||
|
const p = LinearElementEditor.getPointAtIndexGlobalCoordinates(
|
||||||
|
element,
|
||||||
|
startOrEnd === "start" ? 0 : element.points.length - 1,
|
||||||
|
elementsMap,
|
||||||
|
);
|
||||||
|
const mode = isPointInElement(p, boundElement, elementsMap)
|
||||||
|
? "inside"
|
||||||
|
: "orbit";
|
||||||
|
const focusPoint =
|
||||||
|
mode === "inside"
|
||||||
|
? p
|
||||||
|
: projectFixedPointOntoDiagonal(
|
||||||
|
element,
|
||||||
|
p,
|
||||||
|
boundElement,
|
||||||
|
startOrEnd,
|
||||||
|
elementsMap,
|
||||||
|
) || p;
|
||||||
|
const { fixedPoint } = calculateFixedPointForNonElbowArrowBinding(
|
||||||
|
element,
|
||||||
|
boundElement,
|
||||||
|
startOrEnd,
|
||||||
|
elementsMap,
|
||||||
|
focusPoint,
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
mode,
|
||||||
|
elementId: binding.elementId,
|
||||||
|
fixedPoint,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const restoreElementWithProperties = <
|
const restoreElementWithProperties = <
|
||||||
@@ -234,7 +285,10 @@ const restoreElementWithProperties = <
|
|||||||
|
|
||||||
export const restoreElement = (
|
export const restoreElement = (
|
||||||
element: Exclude<ExcalidrawElement, ExcalidrawSelectionElement>,
|
element: Exclude<ExcalidrawElement, ExcalidrawSelectionElement>,
|
||||||
opts?: { deleteInvisibleElements?: boolean },
|
elements: readonly ExcalidrawElement[],
|
||||||
|
opts?: {
|
||||||
|
deleteInvisibleElements?: boolean;
|
||||||
|
},
|
||||||
): typeof element | null => {
|
): typeof element | null => {
|
||||||
element = { ...element };
|
element = { ...element };
|
||||||
|
|
||||||
@@ -321,12 +375,9 @@ export const restoreElement = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
return restoreElementWithProperties(element, {
|
return restoreElementWithProperties(element, {
|
||||||
type:
|
type: "line",
|
||||||
(element.type as ExcalidrawElementType | "draw") === "draw"
|
startBinding: null,
|
||||||
? "line"
|
endBinding: null,
|
||||||
: element.type,
|
|
||||||
startBinding: repairBinding(element, element.startBinding),
|
|
||||||
endBinding: repairBinding(element, element.endBinding),
|
|
||||||
startArrowhead,
|
startArrowhead,
|
||||||
endArrowhead,
|
endArrowhead,
|
||||||
points,
|
points,
|
||||||
@@ -357,8 +408,18 @@ export const restoreElement = (
|
|||||||
|
|
||||||
const base = {
|
const base = {
|
||||||
type: element.type,
|
type: element.type,
|
||||||
startBinding: repairBinding(element, element.startBinding),
|
startBinding: repairBinding(
|
||||||
endBinding: repairBinding(element, element.endBinding),
|
element as ExcalidrawArrowElement,
|
||||||
|
element.startBinding,
|
||||||
|
elements,
|
||||||
|
"start",
|
||||||
|
),
|
||||||
|
endBinding: repairBinding(
|
||||||
|
element as ExcalidrawArrowElement,
|
||||||
|
element.endBinding,
|
||||||
|
elements,
|
||||||
|
"end",
|
||||||
|
),
|
||||||
startArrowhead,
|
startArrowhead,
|
||||||
endArrowhead,
|
endArrowhead,
|
||||||
points,
|
points,
|
||||||
@@ -373,8 +434,6 @@ export const restoreElement = (
|
|||||||
? restoreElementWithProperties(element as ExcalidrawElbowArrowElement, {
|
? restoreElementWithProperties(element as ExcalidrawElbowArrowElement, {
|
||||||
...base,
|
...base,
|
||||||
elbowed: true,
|
elbowed: true,
|
||||||
startBinding: repairBinding(element, element.startBinding),
|
|
||||||
endBinding: repairBinding(element, element.endBinding),
|
|
||||||
fixedSegments:
|
fixedSegments:
|
||||||
element.fixedSegments?.length && base.points.length >= 4
|
element.fixedSegments?.length && base.points.length >= 4
|
||||||
? element.fixedSegments
|
? element.fixedSegments
|
||||||
@@ -535,9 +594,13 @@ export const restoreElements = (
|
|||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
let migratedElement: ExcalidrawElement | null = restoreElement(element, {
|
let migratedElement: ExcalidrawElement | null = restoreElement(
|
||||||
deleteInvisibleElements: opts?.deleteInvisibleElements,
|
element,
|
||||||
});
|
elements,
|
||||||
|
{
|
||||||
|
deleteInvisibleElements: opts?.deleteInvisibleElements,
|
||||||
|
},
|
||||||
|
);
|
||||||
if (migratedElement) {
|
if (migratedElement) {
|
||||||
const localElement = localElementsMap?.get(element.id);
|
const localElement = localElementsMap?.get(element.id);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user