mirror of
https://github.com/excalidraw/excalidraw
synced 2025-07-25 13:58:22 +08:00
Bind mode on precise binding
Fix binding to inside element Fix initial arrow not following cursor (white dot) Fix elbow arrow
This commit is contained in:
@ -139,7 +139,7 @@ export const bindOrUnbindBindingElement = (
|
|||||||
);
|
);
|
||||||
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 (!isElbowArrow(arrow) && (start.focusPoint || end.focusPoint)) {
|
||||||
// If the strategy dictates a focus point override, then
|
// If the strategy dictates a focus point override, then
|
||||||
// update the arrow points to point to the focus point.
|
// update the arrow points to point to the focus point.
|
||||||
const updates: PointsPositionUpdates = new Map();
|
const updates: PointsPositionUpdates = new Map();
|
||||||
|
@ -6233,41 +6233,52 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
multiElement.startBinding.mode === "orbit"
|
multiElement.startBinding.mode === "orbit"
|
||||||
) {
|
) {
|
||||||
const elementsMap = this.scene.getNonDeletedElementsMap();
|
const elementsMap = this.scene.getNonDeletedElementsMap();
|
||||||
const startPoint =
|
const hoveredElement = getHoveredElementForBinding(
|
||||||
LinearElementEditor.getPointAtIndexGlobalCoordinates(
|
pointFrom<GlobalPoint>(scenePointerX, scenePointerY),
|
||||||
multiElement,
|
this.scene.getNonDeletedElements(),
|
||||||
0,
|
this.scene.getNonDeletedElementsMap(),
|
||||||
elementsMap,
|
this.state.zoom,
|
||||||
);
|
|
||||||
const startElement = this.scene.getElement(
|
|
||||||
multiElement.startBinding.elementId,
|
|
||||||
) as ExcalidrawBindableElement;
|
|
||||||
const localPoint = updateBoundPoint(
|
|
||||||
multiElement,
|
|
||||||
"startBinding",
|
|
||||||
multiElement.startBinding,
|
|
||||||
startElement,
|
|
||||||
elementsMap,
|
|
||||||
);
|
);
|
||||||
const avoidancePoint = localPoint
|
if (
|
||||||
? LinearElementEditor.getPointGlobalCoordinates(
|
!hoveredElement ||
|
||||||
|
hoveredElement.id !== multiElement.startBinding.elementId
|
||||||
|
) {
|
||||||
|
const startPoint =
|
||||||
|
LinearElementEditor.getPointAtIndexGlobalCoordinates(
|
||||||
multiElement,
|
multiElement,
|
||||||
localPoint,
|
0,
|
||||||
elementsMap,
|
elementsMap,
|
||||||
)
|
);
|
||||||
: null;
|
const startElement = this.scene.getElement(
|
||||||
if (avoidancePoint && !pointsEqual(startPoint, avoidancePoint)) {
|
multiElement.startBinding.elementId,
|
||||||
const point = LinearElementEditor.pointFromAbsoluteCoords(
|
) as ExcalidrawBindableElement;
|
||||||
|
const localPoint = updateBoundPoint(
|
||||||
multiElement,
|
multiElement,
|
||||||
avoidancePoint,
|
"startBinding",
|
||||||
|
multiElement.startBinding,
|
||||||
|
startElement,
|
||||||
elementsMap,
|
elementsMap,
|
||||||
);
|
);
|
||||||
|
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([[0, { point }]]),
|
new Map([[0, { point }]]),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6933,9 +6944,13 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
clearTimeout(this.bindModeHandler);
|
clearTimeout(this.bindModeHandler);
|
||||||
}
|
}
|
||||||
this.bindModeHandler = null;
|
this.bindModeHandler = null;
|
||||||
this.setState({
|
// We need this iteration to complete binding and change
|
||||||
bindMode: "orbit",
|
// back to orbit mode after that
|
||||||
});
|
setTimeout(() =>
|
||||||
|
this.setState({
|
||||||
|
bindMode: "orbit",
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const scenePointer = viewportCoordsToSceneCoords(
|
const scenePointer = viewportCoordsToSceneCoords(
|
||||||
@ -8494,26 +8509,6 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
event[KEYS.CTRL_OR_CMD] ? null : this.getEffectiveGridSize(),
|
event[KEYS.CTRL_OR_CMD] ? null : this.getEffectiveGridSize(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// for arrows/lines, don't start dragging until a given threshold
|
|
||||||
// to ensure we don't create a 2-point arrow by mistake when
|
|
||||||
// user clicks mouse in a way that it moves a tiny bit (thus
|
|
||||||
// triggering pointermove)
|
|
||||||
if (
|
|
||||||
!pointerDownState.drag.hasOccurred &&
|
|
||||||
(this.state.activeTool.type === "arrow" ||
|
|
||||||
this.state.activeTool.type === "line")
|
|
||||||
) {
|
|
||||||
if (
|
|
||||||
pointDistance(
|
|
||||||
pointFrom(pointerCoords.x, pointerCoords.y),
|
|
||||||
pointFrom(pointerDownState.origin.x, pointerDownState.origin.y),
|
|
||||||
) *
|
|
||||||
this.state.zoom.value <
|
|
||||||
MINIMUM_ARROW_SIZE
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pointerDownState.resize.isResizing) {
|
if (pointerDownState.resize.isResizing) {
|
||||||
pointerDownState.lastCoords.x = pointerCoords.x;
|
pointerDownState.lastCoords.x = pointerCoords.x;
|
||||||
pointerDownState.lastCoords.y = pointerCoords.y;
|
pointerDownState.lastCoords.y = pointerCoords.y;
|
||||||
|
Reference in New Issue
Block a user