mirror of
https://github.com/excalidraw/excalidraw
synced 2025-07-25 13:58:22 +08:00
Include point updates after binding update
Fix point updates when endpoint dragged and opposite endpoint orbits centered focus point only for new arrows
This commit is contained in:
@ -11,11 +11,14 @@ import { type AppState } from "@excalidraw/excalidraw/types";
|
|||||||
import { arrayToMap, invariant, throttleRAF } from "@excalidraw/common";
|
import { arrayToMap, invariant, throttleRAF } from "@excalidraw/common";
|
||||||
import { useCallback, useImperativeHandle, useRef } from "react";
|
import { useCallback, useImperativeHandle, useRef } from "react";
|
||||||
|
|
||||||
import { isArrowElement, isBindableElement } from "@excalidraw/element";
|
import {
|
||||||
|
getGlobalFixedPointForBindableElement,
|
||||||
|
isArrowElement,
|
||||||
|
isBindableElement,
|
||||||
|
} from "@excalidraw/element";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
isLineSegment,
|
isLineSegment,
|
||||||
pointFrom,
|
|
||||||
type GlobalPoint,
|
type GlobalPoint,
|
||||||
type LineSegment,
|
type LineSegment,
|
||||||
} from "@excalidraw/math";
|
} from "@excalidraw/math";
|
||||||
@ -94,9 +97,10 @@ const _renderBinding = (
|
|||||||
const bindable = elementsMap.get(
|
const bindable = elementsMap.get(
|
||||||
binding.elementId,
|
binding.elementId,
|
||||||
) as ExcalidrawBindableElement;
|
) as ExcalidrawBindableElement;
|
||||||
const [x, y] = pointFrom<GlobalPoint>(
|
const [x, y] = getGlobalFixedPointForBindableElement(
|
||||||
bindable.x + bindable.width * binding.fixedPoint[0],
|
binding.fixedPoint,
|
||||||
bindable.y + bindable.height * binding.fixedPoint[1],
|
bindable,
|
||||||
|
elementsMap,
|
||||||
);
|
);
|
||||||
|
|
||||||
context.save();
|
context.save();
|
||||||
@ -128,9 +132,10 @@ const _renderBindableBinding = (
|
|||||||
const bindable = elementsMap.get(
|
const bindable = elementsMap.get(
|
||||||
binding.elementId,
|
binding.elementId,
|
||||||
) as ExcalidrawBindableElement;
|
) as ExcalidrawBindableElement;
|
||||||
const [x, y] = pointFrom<GlobalPoint>(
|
const [x, y] = getGlobalFixedPointForBindableElement(
|
||||||
bindable.x + bindable.width * binding.fixedPoint[0],
|
binding.fixedPoint,
|
||||||
bindable.y + bindable.height * binding.fixedPoint[1],
|
bindable,
|
||||||
|
elementsMap,
|
||||||
);
|
);
|
||||||
|
|
||||||
context.save();
|
context.save();
|
||||||
|
@ -125,6 +125,9 @@ export const bindOrUnbindBindingElement = (
|
|||||||
draggingPoints: PointsPositionUpdates,
|
draggingPoints: PointsPositionUpdates,
|
||||||
scene: Scene,
|
scene: Scene,
|
||||||
appState: AppState,
|
appState: AppState,
|
||||||
|
opts?: {
|
||||||
|
newArrow: boolean;
|
||||||
|
},
|
||||||
) => {
|
) => {
|
||||||
const { start, end } = getBindingStrategyForDraggingBindingElementEndpoints(
|
const { start, end } = getBindingStrategyForDraggingBindingElementEndpoints(
|
||||||
arrow,
|
arrow,
|
||||||
@ -132,9 +135,43 @@ export const bindOrUnbindBindingElement = (
|
|||||||
scene.getNonDeletedElementsMap(),
|
scene.getNonDeletedElementsMap(),
|
||||||
scene.getNonDeletedElements(),
|
scene.getNonDeletedElements(),
|
||||||
appState,
|
appState,
|
||||||
|
opts,
|
||||||
);
|
);
|
||||||
bindOrUnbindBindingElementEdge(arrow, start, "start", scene);
|
bindOrUnbindBindingElementEdge(arrow, start, "start", scene);
|
||||||
bindOrUnbindBindingElementEdge(arrow, end, "end", scene);
|
bindOrUnbindBindingElementEdge(arrow, end, "end", scene);
|
||||||
|
if (start.focusPoint || end.focusPoint) {
|
||||||
|
// If the strategy dictates a focus point override, then
|
||||||
|
// update the arrow points to point to the focus point.
|
||||||
|
const updates: PointsPositionUpdates = new Map();
|
||||||
|
|
||||||
|
if (start.focusPoint) {
|
||||||
|
updates.set(0, {
|
||||||
|
point:
|
||||||
|
updateBoundPoint(
|
||||||
|
arrow,
|
||||||
|
"startBinding",
|
||||||
|
arrow.startBinding,
|
||||||
|
start.element,
|
||||||
|
scene.getNonDeletedElementsMap(),
|
||||||
|
) || arrow.points[0],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end.focusPoint) {
|
||||||
|
updates.set(arrow.points.length - 1, {
|
||||||
|
point:
|
||||||
|
updateBoundPoint(
|
||||||
|
arrow,
|
||||||
|
"endBinding",
|
||||||
|
arrow.endBinding,
|
||||||
|
end.element,
|
||||||
|
scene.getNonDeletedElementsMap(),
|
||||||
|
) || arrow.points[arrow.points.length - 1],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
LinearElementEditor.movePoints(arrow, scene, updates);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const bindOrUnbindBindingElementEdge = (
|
const bindOrUnbindBindingElementEdge = (
|
||||||
@ -193,6 +230,9 @@ const bindingStrategyForEndpointDragging = (
|
|||||||
elements: readonly Ordered<NonDeletedExcalidrawElement>[],
|
elements: readonly Ordered<NonDeletedExcalidrawElement>[],
|
||||||
zoom: AppState["zoom"],
|
zoom: AppState["zoom"],
|
||||||
globalBindMode?: AppState["bindMode"],
|
globalBindMode?: AppState["bindMode"],
|
||||||
|
opts?: {
|
||||||
|
newArrow: boolean;
|
||||||
|
},
|
||||||
): { current: BindingStrategy; other: BindingStrategy } => {
|
): { current: BindingStrategy; other: BindingStrategy } => {
|
||||||
let current: BindingStrategy = { mode: undefined };
|
let current: BindingStrategy = { mode: undefined };
|
||||||
let other: BindingStrategy = { mode: undefined };
|
let other: BindingStrategy = { mode: undefined };
|
||||||
@ -233,10 +273,12 @@ const bindingStrategyForEndpointDragging = (
|
|||||||
current = {
|
current = {
|
||||||
element: hovered,
|
element: hovered,
|
||||||
mode: "orbit",
|
mode: "orbit",
|
||||||
focusPoint: pointFrom<GlobalPoint>(
|
focusPoint: opts?.newArrow
|
||||||
hovered.x + hovered.width / 2,
|
? pointFrom<GlobalPoint>(
|
||||||
hovered.y + hovered.height / 2,
|
hovered.x + hovered.width / 2,
|
||||||
),
|
hovered.y + hovered.height / 2,
|
||||||
|
)
|
||||||
|
: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
return { current, other };
|
return { current, other };
|
||||||
@ -273,10 +315,12 @@ const bindingStrategyForEndpointDragging = (
|
|||||||
current = {
|
current = {
|
||||||
element: hovered,
|
element: hovered,
|
||||||
mode: "orbit",
|
mode: "orbit",
|
||||||
focusPoint: pointFrom<GlobalPoint>(
|
focusPoint: opts?.newArrow
|
||||||
hovered.x + hovered.width / 2,
|
? pointFrom<GlobalPoint>(
|
||||||
hovered.y + hovered.height / 2,
|
hovered.x + hovered.width / 2,
|
||||||
),
|
hovered.y + hovered.height / 2,
|
||||||
|
)
|
||||||
|
: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
return { current, other };
|
return { current, other };
|
||||||
@ -302,6 +346,9 @@ const getBindingStrategyForDraggingBindingElementEndpoints = (
|
|||||||
elementsMap: NonDeletedSceneElementsMap,
|
elementsMap: NonDeletedSceneElementsMap,
|
||||||
elements: readonly Ordered<NonDeletedExcalidrawElement>[],
|
elements: readonly Ordered<NonDeletedExcalidrawElement>[],
|
||||||
appState: AppState,
|
appState: AppState,
|
||||||
|
opts?: {
|
||||||
|
newArrow: boolean;
|
||||||
|
},
|
||||||
): { start: BindingStrategy; end: BindingStrategy } => {
|
): { start: BindingStrategy; end: BindingStrategy } => {
|
||||||
const globalBindMode = appState.bindMode || "focus";
|
const globalBindMode = appState.bindMode || "focus";
|
||||||
const startIdx = 0;
|
const startIdx = 0;
|
||||||
@ -330,7 +377,18 @@ const getBindingStrategyForDraggingBindingElementEndpoints = (
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
start: hovered
|
start: hovered
|
||||||
? { element: hovered, mode: hit ? "inside" : "outside" }
|
? hit
|
||||||
|
? { element: hovered, mode: "inside" }
|
||||||
|
: opts?.newArrow
|
||||||
|
? {
|
||||||
|
element: hovered,
|
||||||
|
mode: "orbit",
|
||||||
|
focusPoint: pointFrom<GlobalPoint>(
|
||||||
|
hovered.x + hovered.width / 2,
|
||||||
|
hovered.y + hovered.height / 2,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
: { element: hovered, mode: "inside" }
|
||||||
: { mode: undefined },
|
: { mode: undefined },
|
||||||
end: { mode: undefined },
|
end: { mode: undefined },
|
||||||
};
|
};
|
||||||
@ -372,6 +430,7 @@ const getBindingStrategyForDraggingBindingElementEndpoints = (
|
|||||||
elements,
|
elements,
|
||||||
appState.zoom,
|
appState.zoom,
|
||||||
globalBindMode,
|
globalBindMode,
|
||||||
|
opts,
|
||||||
);
|
);
|
||||||
|
|
||||||
return { start: current, end: other };
|
return { start: current, end: other };
|
||||||
@ -393,6 +452,7 @@ const getBindingStrategyForDraggingBindingElementEndpoints = (
|
|||||||
elements,
|
elements,
|
||||||
appState.zoom,
|
appState.zoom,
|
||||||
globalBindMode,
|
globalBindMode,
|
||||||
|
opts,
|
||||||
);
|
);
|
||||||
|
|
||||||
return { start: other, end: current };
|
return { start: other, end: current };
|
||||||
@ -560,21 +620,6 @@ export const bindBindingElement = (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isBindingElementSimpleAndAlreadyBound = (
|
|
||||||
linearElement: NonDeleted<ExcalidrawArrowElement>,
|
|
||||||
alreadyBoundToId: ExcalidrawBindableElement["id"] | undefined,
|
|
||||||
bindableElement: ExcalidrawBindableElement,
|
|
||||||
): boolean => {
|
|
||||||
return (
|
|
||||||
alreadyBoundToId === bindableElement.id &&
|
|
||||||
isBindingElementSimple(linearElement)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const isBindingElementSimple = (
|
|
||||||
linearElement: NonDeleted<ExcalidrawArrowElement>,
|
|
||||||
): boolean => linearElement.points.length < 3 && !isElbowArrow(linearElement);
|
|
||||||
|
|
||||||
export const unbindBindingElement = (
|
export const unbindBindingElement = (
|
||||||
arrow: NonDeleted<ExcalidrawArrowElement>,
|
arrow: NonDeleted<ExcalidrawArrowElement>,
|
||||||
startOrEnd: "start" | "end",
|
startOrEnd: "start" | "end",
|
||||||
@ -1115,7 +1160,7 @@ export const snapToMid = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const updateBoundPoint = (
|
export const updateBoundPoint = (
|
||||||
linearElement: NonDeleted<ExcalidrawArrowElement>,
|
arrow: NonDeleted<ExcalidrawArrowElement>,
|
||||||
startOrEnd: "startBinding" | "endBinding",
|
startOrEnd: "startBinding" | "endBinding",
|
||||||
binding: FixedPointBinding | null | undefined,
|
binding: FixedPointBinding | null | undefined,
|
||||||
bindableElement: ExcalidrawBindableElement,
|
bindableElement: ExcalidrawBindableElement,
|
||||||
@ -1124,36 +1169,37 @@ export const updateBoundPoint = (
|
|||||||
if (
|
if (
|
||||||
binding == null ||
|
binding == null ||
|
||||||
// We only need to update the other end if this is a 2 point line element
|
// We only need to update the other end if this is a 2 point line element
|
||||||
(binding.elementId !== bindableElement.id &&
|
(binding.elementId !== bindableElement.id && arrow.points.length > 2)
|
||||||
linearElement.points.length > 2)
|
|
||||||
) {
|
) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fixedPoint = normalizeFixedPoint(binding.fixedPoint);
|
const fixedPoint = normalizeFixedPoint(binding.fixedPoint);
|
||||||
const globalMidPoint = elementCenterPoint(bindableElement, elementsMap);
|
const global = getGlobalFixedPointForBindableElement(
|
||||||
const global = pointFrom<GlobalPoint>(
|
fixedPoint,
|
||||||
bindableElement.x + fixedPoint[0] * bindableElement.width,
|
bindableElement,
|
||||||
bindableElement.y + fixedPoint[1] * bindableElement.height,
|
elementsMap,
|
||||||
);
|
|
||||||
const rotatedGlobal = pointRotateRads(
|
|
||||||
global,
|
|
||||||
globalMidPoint,
|
|
||||||
bindableElement.angle,
|
|
||||||
);
|
);
|
||||||
|
const element =
|
||||||
|
arrow.points.length === 1
|
||||||
|
? {
|
||||||
|
...arrow,
|
||||||
|
points: [arrow.points[0], arrow.points[0]],
|
||||||
|
}
|
||||||
|
: arrow;
|
||||||
const maybeOutlineGlobal =
|
const maybeOutlineGlobal =
|
||||||
binding.mode === "orbit"
|
binding.mode === "orbit"
|
||||||
? getOutlineAvoidingPoint(
|
? getOutlineAvoidingPoint(
|
||||||
linearElement,
|
element,
|
||||||
bindableElement,
|
bindableElement,
|
||||||
rotatedGlobal,
|
global,
|
||||||
startOrEnd === "startBinding" ? 0 : linearElement.points.length - 1,
|
startOrEnd === "startBinding" ? 0 : arrow.points.length - 1,
|
||||||
elementsMap,
|
elementsMap,
|
||||||
)
|
)
|
||||||
: rotatedGlobal;
|
: global;
|
||||||
|
|
||||||
return LinearElementEditor.pointFromAbsoluteCoords(
|
return LinearElementEditor.pointFromAbsoluteCoords(
|
||||||
linearElement,
|
arrow,
|
||||||
maybeOutlineGlobal,
|
maybeOutlineGlobal,
|
||||||
elementsMap,
|
elementsMap,
|
||||||
);
|
);
|
||||||
|
@ -23,9 +23,9 @@ import {
|
|||||||
} from "@excalidraw/common";
|
} from "@excalidraw/common";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
bindingBorderTest,
|
||||||
deconstructLinearOrFreeDrawElement,
|
deconstructLinearOrFreeDrawElement,
|
||||||
getHoveredElementForBinding,
|
getHoveredElementForBinding,
|
||||||
hitElementItself,
|
|
||||||
isPathALoop,
|
isPathALoop,
|
||||||
type Store,
|
type Store,
|
||||||
} from "@excalidraw/element";
|
} from "@excalidraw/element";
|
||||||
@ -42,6 +42,7 @@ import type {
|
|||||||
} from "@excalidraw/excalidraw/types";
|
} from "@excalidraw/excalidraw/types";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
getGlobalFixedPointForBindableElement,
|
||||||
getOutlineAvoidingPoint,
|
getOutlineAvoidingPoint,
|
||||||
isBindingEnabled,
|
isBindingEnabled,
|
||||||
maybeSuggestBindingsForBindingElementAtCoords,
|
maybeSuggestBindingsForBindingElementAtCoords,
|
||||||
@ -55,7 +56,12 @@ import {
|
|||||||
import { headingIsHorizontal, vectorToHeading } from "./heading";
|
import { headingIsHorizontal, vectorToHeading } from "./heading";
|
||||||
import { mutateElement } from "./mutateElement";
|
import { mutateElement } from "./mutateElement";
|
||||||
import { getBoundTextElement, handleBindTextResize } from "./textElement";
|
import { getBoundTextElement, handleBindTextResize } from "./textElement";
|
||||||
import { isArrowElement, isBindingElement, isElbowArrow } from "./typeChecks";
|
import {
|
||||||
|
isArrowElement,
|
||||||
|
isBindingElement,
|
||||||
|
isElbowArrow,
|
||||||
|
isSimpleArrow,
|
||||||
|
} from "./typeChecks";
|
||||||
|
|
||||||
import { ShapeCache, toggleLinePolygonState } from "./shape";
|
import { ShapeCache, toggleLinePolygonState } from "./shape";
|
||||||
|
|
||||||
@ -1936,12 +1942,13 @@ const pointDraggingUpdates = (
|
|||||||
elements: readonly Ordered<NonDeletedExcalidrawElement>[],
|
elements: readonly Ordered<NonDeletedExcalidrawElement>[],
|
||||||
appState: AppState,
|
appState: AppState,
|
||||||
): PointsPositionUpdates => {
|
): PointsPositionUpdates => {
|
||||||
|
const [, , , , cx, cy] = getElementAbsoluteCoords(element, elementsMap, true);
|
||||||
const hasMidPoints =
|
const hasMidPoints =
|
||||||
selectedPointsIndices.filter(
|
selectedPointsIndices.filter(
|
||||||
(_, idx) => idx > 0 && idx < element.points.length - 1,
|
(_, idx) => idx > 0 && idx < element.points.length - 1,
|
||||||
).length > 0;
|
).length > 0;
|
||||||
|
|
||||||
return new Map(
|
const updates = new Map(
|
||||||
selectedPointsIndices.map((pointIndex) => {
|
selectedPointsIndices.map((pointIndex) => {
|
||||||
let newPointPosition: LocalPoint =
|
let newPointPosition: LocalPoint =
|
||||||
pointIndex === lastClickedPoint
|
pointIndex === lastClickedPoint
|
||||||
@ -1958,14 +1965,10 @@ const pointDraggingUpdates = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
isSimpleArrow(element) &&
|
||||||
!hasMidPoints &&
|
!hasMidPoints &&
|
||||||
(pointIndex === 0 || pointIndex === element.points.length - 1)
|
(pointIndex === 0 || pointIndex === element.points.length - 1)
|
||||||
) {
|
) {
|
||||||
const [, , , , cx, cy] = getElementAbsoluteCoords(
|
|
||||||
element,
|
|
||||||
elementsMap,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
let newGlobalPointPosition = pointRotateRads(
|
let newGlobalPointPosition = pointRotateRads(
|
||||||
pointFrom<GlobalPoint>(
|
pointFrom<GlobalPoint>(
|
||||||
element.x + newPointPosition[0],
|
element.x + newPointPosition[0],
|
||||||
@ -1988,12 +1991,12 @@ const pointDraggingUpdates = (
|
|||||||
);
|
);
|
||||||
const otherPointInsideElement =
|
const otherPointInsideElement =
|
||||||
!!hoveredElement &&
|
!!hoveredElement &&
|
||||||
hitElementItself({
|
!!bindingBorderTest(
|
||||||
element: hoveredElement,
|
hoveredElement,
|
||||||
point: otherGlobalPoint,
|
otherGlobalPoint,
|
||||||
elementsMap,
|
elementsMap,
|
||||||
threshold: 0,
|
appState.zoom,
|
||||||
});
|
);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
isBindingEnabled(appState) &&
|
isBindingEnabled(appState) &&
|
||||||
@ -2029,4 +2032,60 @@ const pointDraggingUpdates = (
|
|||||||
];
|
];
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (isSimpleArrow(element)) {
|
||||||
|
const adjacentPointIndices =
|
||||||
|
element.points.length === 2
|
||||||
|
? [0, 1]
|
||||||
|
: element.points.length === 3
|
||||||
|
? [1]
|
||||||
|
: [1, element.points.length - 2];
|
||||||
|
|
||||||
|
adjacentPointIndices
|
||||||
|
.filter((adjacentPointIndex) =>
|
||||||
|
selectedPointsIndices.includes(adjacentPointIndex),
|
||||||
|
)
|
||||||
|
.flatMap((adjacentPointIndex) =>
|
||||||
|
element.points.length === 3
|
||||||
|
? [0, 2]
|
||||||
|
: adjacentPointIndex === 1
|
||||||
|
? 0
|
||||||
|
: element.points.length - 1,
|
||||||
|
)
|
||||||
|
.forEach((pointIndex) => {
|
||||||
|
const binding =
|
||||||
|
element[pointIndex === 0 ? "startBinding" : "endBinding"];
|
||||||
|
const bindingIsOrbiting = binding?.mode === "orbit";
|
||||||
|
if (bindingIsOrbiting) {
|
||||||
|
const hoveredElement = elementsMap.get(
|
||||||
|
binding.elementId,
|
||||||
|
) as ExcalidrawBindableElement;
|
||||||
|
const focusGlobalPoint = getGlobalFixedPointForBindableElement(
|
||||||
|
binding.fixedPoint,
|
||||||
|
hoveredElement,
|
||||||
|
elementsMap,
|
||||||
|
);
|
||||||
|
const newGlobalPointPosition = getOutlineAvoidingPoint(
|
||||||
|
element,
|
||||||
|
hoveredElement,
|
||||||
|
focusGlobalPoint,
|
||||||
|
pointIndex,
|
||||||
|
elementsMap,
|
||||||
|
);
|
||||||
|
const newPointPosition = LinearElementEditor.createPointAt(
|
||||||
|
element,
|
||||||
|
elementsMap,
|
||||||
|
newGlobalPointPosition[0] - linearElementEditor.pointerOffset.x,
|
||||||
|
newGlobalPointPosition[1] - linearElementEditor.pointerOffset.y,
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
updates.set(pointIndex, {
|
||||||
|
point: newPointPosition,
|
||||||
|
isDragging: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return updates;
|
||||||
};
|
};
|
||||||
|
@ -276,6 +276,7 @@ export const actionFinalize = register({
|
|||||||
]),
|
]),
|
||||||
scene,
|
scene,
|
||||||
appState,
|
appState,
|
||||||
|
{ newArrow: true },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -239,6 +239,7 @@ import {
|
|||||||
calculateFixedPointForNonElbowArrowBinding,
|
calculateFixedPointForNonElbowArrowBinding,
|
||||||
normalizeFixedPoint,
|
normalizeFixedPoint,
|
||||||
bindOrUnbindBindingElement,
|
bindOrUnbindBindingElement,
|
||||||
|
updateBoundPoint,
|
||||||
} from "@excalidraw/element";
|
} from "@excalidraw/element";
|
||||||
|
|
||||||
import type { GlobalPoint, LocalPoint, Radians } from "@excalidraw/math";
|
import type { GlobalPoint, LocalPoint, Radians } from "@excalidraw/math";
|
||||||
@ -6236,40 +6237,31 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
const startElement = this.scene.getElement(
|
const startElement = this.scene.getElement(
|
||||||
multiElement.startBinding.elementId,
|
multiElement.startBinding.elementId,
|
||||||
) as ExcalidrawBindableElement;
|
) as ExcalidrawBindableElement;
|
||||||
const avoidancePoint = getOutlineAvoidingPoint(
|
const localPoint = updateBoundPoint(
|
||||||
multiElement,
|
multiElement,
|
||||||
|
"startBinding",
|
||||||
|
multiElement.startBinding,
|
||||||
startElement,
|
startElement,
|
||||||
startPoint,
|
|
||||||
0,
|
|
||||||
elementsMap,
|
elementsMap,
|
||||||
);
|
);
|
||||||
if (!pointsEqual(startPoint, avoidancePoint)) {
|
const avoidancePoint = localPoint
|
||||||
|
? LinearElementEditor.getPointGlobalCoordinates(
|
||||||
|
multiElement,
|
||||||
|
localPoint,
|
||||||
|
elementsMap,
|
||||||
|
)
|
||||||
|
: null;
|
||||||
|
if (avoidancePoint && !pointsEqual(startPoint, avoidancePoint)) {
|
||||||
|
const point = LinearElementEditor.pointFromAbsoluteCoords(
|
||||||
|
multiElement,
|
||||||
|
avoidancePoint,
|
||||||
|
elementsMap,
|
||||||
|
);
|
||||||
|
|
||||||
LinearElementEditor.movePoints(
|
LinearElementEditor.movePoints(
|
||||||
multiElement,
|
multiElement,
|
||||||
this.scene,
|
this.scene,
|
||||||
new Map([
|
new Map([[0, { point }]]),
|
||||||
[
|
|
||||||
0,
|
|
||||||
{
|
|
||||||
point: LinearElementEditor.pointFromAbsoluteCoords(
|
|
||||||
multiElement,
|
|
||||||
avoidancePoint,
|
|
||||||
elementsMap,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
]),
|
|
||||||
{
|
|
||||||
startBinding: {
|
|
||||||
...multiElement.startBinding,
|
|
||||||
...calculateFixedPointForNonElbowArrowBinding(
|
|
||||||
multiElement,
|
|
||||||
startElement,
|
|
||||||
"start",
|
|
||||||
elementsMap,
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8168,6 +8160,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
]),
|
]),
|
||||||
this.scene,
|
this.scene,
|
||||||
this.state,
|
this.state,
|
||||||
|
{ newArrow: true },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.setState((prevState) => {
|
this.setState((prevState) => {
|
||||||
|
Reference in New Issue
Block a user