Small positional fixes

This commit is contained in:
Mark Tolmacs
2025-08-30 21:54:25 +02:00
parent 92b9051838
commit 57b7f8bd42
3 changed files with 108 additions and 86 deletions

View File

@@ -221,6 +221,13 @@ export const getStartGlobalEndLocalPointsForSimpleArrowBinding = (
elementsMap,
);
endLocalPoint = newEndLocalPoint ?? endLocalPoint;
if (end.focusPoint[0] === 0.5001 && end.focusPoint[1] === 0.5001) {
endLocalPoint = LinearElementEditor.pointFromAbsoluteCoords(
arrow,
elementCenterPoint(arrow, elementsMap),
elementsMap,
);
}
}
if (start.mode) {
@@ -250,6 +257,9 @@ export const getStartGlobalEndLocalPointsForSimpleArrowBinding = (
elementsMap,
)
: startGlobalPoint;
if (start.focusPoint[0] === 0.5001 && start.focusPoint[1] === 0.5001) {
startGlobalPoint = elementCenterPoint(arrow, elementsMap);
}
}
return [
@@ -1045,51 +1055,6 @@ export const bindPointToSnapToElementOutline = (
return intersection;
};
export const getOutlineAvoidingPoint = (
element: NonDeleted<ExcalidrawArrowElement>,
hoveredElement: ExcalidrawBindableElement | null,
coords: GlobalPoint,
pointIndex: number,
elementsMap: ElementsMap,
customIntersector?: LineSegment<GlobalPoint>,
): GlobalPoint => {
if (hoveredElement) {
return bindPointToSnapToElementOutline(
{
...element,
x: pointIndex === 0 ? coords[0] : element.x,
y: pointIndex === 0 ? coords[1] : element.y,
points:
pointIndex === 0
? [
pointFrom<LocalPoint>(0, 0),
...element.points
.slice(1)
.map((p) =>
pointFrom<LocalPoint>(
p[0] - (coords[0] - element.x),
p[1] - (coords[1] - element.y),
),
),
]
: [
...element.points.slice(0, -1),
pointFrom<LocalPoint>(
coords[0] - element.x,
coords[1] - element.y,
),
],
},
hoveredElement,
pointIndex === 0 ? "start" : "end",
elementsMap,
customIntersector,
);
}
return coords;
};
export const avoidRectangularCorner = (
element: ExcalidrawBindableElement,
elementsMap: ElementsMap,
@@ -1336,20 +1301,44 @@ export const updateBoundPoint = (
return null;
}
const fixedPoint = normalizeFixedPoint(binding.fixedPoint);
const global = getGlobalFixedPointForBindableElement(
fixedPoint,
normalizeFixedPoint(binding.fixedPoint),
bindableElement,
elementsMap,
);
const pointIndex =
startOrEnd === "startBinding" ? 0 : arrow.points.length - 1;
const maybeOutlineGlobal =
binding.mode === "orbit"
? getOutlineAvoidingPoint(
arrow,
binding.mode === "orbit" && bindableElement
? bindPointToSnapToElementOutline(
{
...arrow,
x: pointIndex === 0 ? global[0] : arrow.x,
y: pointIndex === 0 ? global[1] : arrow.y,
points:
pointIndex === 0
? [
pointFrom<LocalPoint>(0, 0),
...arrow.points
.slice(1)
.map((p) =>
pointFrom<LocalPoint>(
p[0] - (global[0] - arrow.x),
p[1] - (global[1] - arrow.y),
),
),
]
: [
...arrow.points.slice(0, -1),
pointFrom<LocalPoint>(
global[0] - arrow.x,
global[1] - arrow.y,
),
],
},
bindableElement,
global,
startOrEnd === "startBinding" ? 0 : arrow.points.length - 1,
pointIndex === 0 ? "start" : "end",
elementsMap,
)
: global;

View File

@@ -344,6 +344,21 @@ export class LinearElementEditor {
);
LinearElementEditor.movePoints(element, app.scene, positions, updates);
// Move the arrow over the bindable object in terms of z-index
if (isBindingElement(element)) {
moveArrowAboveBindable(
LinearElementEditor.getPointGlobalCoordinates(
element,
element.points[element.points.length - 1],
elementsMap,
),
element,
elements,
elementsMap,
app.scene,
);
}
}
// Suggest bindings for first and last point if selected
@@ -481,6 +496,23 @@ export class LinearElementEditor {
);
LinearElementEditor.movePoints(element, app.scene, positions, updates);
// Move the arrow over the bindable object in terms of z-index
if (isBindingElement(element) && startIsSelected !== endIsSelected) {
moveArrowAboveBindable(
LinearElementEditor.getPointGlobalCoordinates(
element,
startIsSelected
? element.points[0]
: element.points[element.points.length - 1],
elementsMap,
),
element,
elements,
elementsMap,
app.scene,
);
}
}
// Attached text might need to update if arrow dimensions change
@@ -2097,41 +2129,40 @@ const pointDraggingUpdates = (
endLocalPoint[1] + (startGlobalPoint[1] - element.y),
);
if (startIsDragged !== endIsDragged) {
moveArrowAboveBindable(
startIsDragged
? startGlobalPoint
: LinearElementEditor.getPointGlobalCoordinates(
element,
finalEndLocalPoint,
elementsMap,
),
element,
elements,
elementsMap,
app.scene,
);
}
const indices = Array.from(
new Set([0, element.points.length - 1, ...selectedPointsIndices]),
);
const updates: PointMoveOtherUpdates = {};
if (start.mode) {
updates.startBinding = {
elementId: start.element.id,
mode: start.mode,
...calculateFixedPointForNonElbowArrowBinding(
element,
start.element,
"start",
elementsMap,
start.focusPoint,
),
};
}
if (end.mode) {
updates.endBinding = {
elementId: end.element.id,
mode: end.mode,
...calculateFixedPointForNonElbowArrowBinding(
element,
end.element,
"end",
elementsMap,
end.focusPoint,
),
};
}
return {
updates: start.mode
? {
startBinding: {
elementId: start.element.id,
mode: start.mode,
...calculateFixedPointForNonElbowArrowBinding(
element,
start.element,
"start",
elementsMap,
),
},
}
: undefined,
updates: start.mode || end.mode ? updates : undefined,
positions: new Map(
indices.map((idx) => {
return [

View File

@@ -969,19 +969,21 @@ class App extends React.Component<AppProps, AppState> {
const event =
this.lastPointerMoveEvent ?? this.lastPointerDownEvent?.nativeEvent;
invariant(event, "Last event must exist");
const deltaX = x - this.state.selectedLinearElement.pointerOffset.x;
const deltaY = y - this.state.selectedLinearElement.pointerOffset.y;
const newState = this.state.multiElement
? LinearElementEditor.handlePointerMove(
event,
this,
x - this.state.selectedLinearElement.pointerOffset.x,
y - this.state.selectedLinearElement.pointerOffset.y,
deltaX,
deltaY,
this.state.selectedLinearElement,
)
: LinearElementEditor.handlePointDragging(
event,
this,
x - this.state.selectedLinearElement.pointerOffset.x,
y - this.state.selectedLinearElement.pointerOffset.y,
deltaX,
deltaY,
this.state.selectedLinearElement,
);
this.setState(newState);