Apply outline tracking to simple arrows as well

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
This commit is contained in:
Mark Tolmacs 2025-03-02 11:37:35 +01:00
parent f354285d69
commit e459ea0cc7
3 changed files with 68 additions and 9 deletions

View file

@ -966,6 +966,7 @@ export const bindPointToSnapToElementOutline = (
), ),
otherPoint, otherPoint,
), ),
adjacentPoint,
), ),
).sort( ).sort(
(g, h) => (g, h) =>
@ -1017,7 +1018,31 @@ export const bindPointToSnapToElementOutline = (
); );
} }
return edgePoint; const currentDistance = pointDistance(edgePoint, center);
const fullDistance = Math.max(
pointDistance(intersection ?? edgePoint, center),
1e-5, // Avoid division by zero
);
const ratio = round(currentDistance / fullDistance);
switch (true) {
case ratio > 0.5:
return pointFromVector(
vectorScale(
vectorNormalize(
vectorFromPoint(intersection ?? center, adjacentPoint),
),
-FIXED_BINDING_DISTANCE,
),
intersection ?? edgePoint,
);
default:
if (elbowed) {
return headingToMidBindPoint(edgePoint, bindableElement, aabb);
}
return edgePoint;
}
}; };
export const avoidRectangularCorner = ( export const avoidRectangularCorner = (

View file

@ -258,7 +258,7 @@ export class LinearElementEditor {
return null; return null;
} }
const { elementId } = linearElementEditor; const { elementId } = linearElementEditor;
const elementsMap = scene.getNonDeletedElementsMap(); const elementsMap = app.scene.getNonDeletedElementsMap();
const element = LinearElementEditor.getElement(elementId, elementsMap); const element = LinearElementEditor.getElement(elementId, elementsMap);
if (!element) { if (!element) {
return null; return null;
@ -334,19 +334,54 @@ export class LinearElementEditor {
LinearElementEditor.movePoints( LinearElementEditor.movePoints(
element, element,
selectedPointsIndices.map((pointIndex) => { selectedPointsIndices.map((pointIndex) => {
let p = pointFrom<GlobalPoint>(
element.x + element.points[pointIndex][0] + deltaX,
element.y + element.points[pointIndex][1] + deltaY,
);
if (
pointIndex === lastClickedPoint &&
(pointIndex === 0 || pointIndex === element.points.length - 1)
) {
const hoveredElement = getHoveredElementForBinding(
{
x: scenePointerX,
y: scenePointerY,
},
app.scene.getNonDeletedElements(),
app.scene.getNonDeletedElementsMap(),
app.state.zoom,
isElbowArrow(element),
isElbowArrow(element),
);
if (hoveredElement) {
const newPoints = Array.from(element.points);
newPoints[pointIndex] = pointFrom(
element.points[pointIndex][0] + deltaX,
element.points[pointIndex][1] + deltaY,
);
p = bindPointToSnapToElementOutline(
{
...element,
points: newPoints,
},
hoveredElement,
pointIndex === 0 ? "start" : "end",
);
}
}
const newPointPosition: LocalPoint = const newPointPosition: LocalPoint =
pointIndex === lastClickedPoint pointIndex === lastClickedPoint
? LinearElementEditor.createPointAt( ? LinearElementEditor.createPointAt(
element, element,
elementsMap, elementsMap,
scenePointerX - linearElementEditor.pointerOffset.x, p[0],
scenePointerY - linearElementEditor.pointerOffset.y, p[1],
// p[0] - linearElementEditor.pointerOffset.x,
// p[1] - linearElementEditor.pointerOffset.y,
event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(), event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(),
) )
: pointFrom( : pointFrom(p[0] - element.x, p[1] - element.y);
element.points[pointIndex][0] + deltaX,
element.points[pointIndex][1] + deltaY,
);
return { return {
index: pointIndex, index: pointIndex,
point: newPointPosition, point: newPointPosition,

View file

@ -8273,7 +8273,6 @@ class App extends React.Component<AppProps, AppState> {
); );
}, },
linearElementEditor, linearElementEditor,
this.scene,
); );
if (newLinearElementEditor) { if (newLinearElementEditor) {
pointerDownState.lastCoords.x = pointerCoords.x; pointerDownState.lastCoords.x = pointerCoords.x;