mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
Multipoint arrows now have single point commit in binding zones
This commit is contained in:
parent
ad8220c529
commit
11fe608f9a
3 changed files with 92 additions and 25 deletions
|
@ -238,24 +238,23 @@ export class LinearElementEditor {
|
|||
});
|
||||
}
|
||||
|
||||
static getOutlineAvoidingPoint(
|
||||
static getOutlineAvoidingPointOrNull(
|
||||
element: NonDeleted<ExcalidrawLinearElement>,
|
||||
coords: { x: number; y: number },
|
||||
pointIndex: number,
|
||||
app: AppClassProperties,
|
||||
): GlobalPoint {
|
||||
const elbowed = isElbowArrow(element);
|
||||
) {
|
||||
const hoveredElement = getHoveredElementForBinding(
|
||||
coords,
|
||||
app.scene.getNonDeletedElements(),
|
||||
app.scene.getNonDeletedElementsMap(),
|
||||
app.state.zoom,
|
||||
true,
|
||||
elbowed,
|
||||
isElbowArrow(element),
|
||||
);
|
||||
const p = pointFrom<GlobalPoint>(coords.x, coords.y);
|
||||
|
||||
if (hoveredElement) {
|
||||
const p = pointFrom<GlobalPoint>(coords.x, coords.y);
|
||||
const newPoints = Array.from(element.points);
|
||||
newPoints[pointIndex] = pointFrom<LocalPoint>(
|
||||
p[0] - element.x,
|
||||
|
@ -273,9 +272,29 @@ export class LinearElementEditor {
|
|||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static getOutlineAvoidingPoint(
|
||||
element: NonDeleted<ExcalidrawLinearElement>,
|
||||
coords: { x: number; y: number },
|
||||
pointIndex: number,
|
||||
app: AppClassProperties,
|
||||
): GlobalPoint {
|
||||
const p = LinearElementEditor.getOutlineAvoidingPointOrNull(
|
||||
element,
|
||||
coords,
|
||||
pointIndex,
|
||||
app,
|
||||
);
|
||||
|
||||
if (p) {
|
||||
return p;
|
||||
}
|
||||
|
||||
return pointFrom<GlobalPoint>(coords.x, coords.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns whether point was dragged
|
||||
*/
|
||||
|
|
|
@ -91,10 +91,26 @@ export const actionFinalize = register({
|
|||
multiPointElement.type !== "freedraw" &&
|
||||
appState.lastPointerDownWith !== "touch"
|
||||
) {
|
||||
const { points, lastCommittedPoint } = multiPointElement;
|
||||
const { x: rx, y: ry, points, lastCommittedPoint } = multiPointElement;
|
||||
const lastGlobalPoint = pointFrom<GlobalPoint>(
|
||||
rx + points[points.length - 1][0],
|
||||
ry + points[points.length - 1][1],
|
||||
);
|
||||
const hoveredElementForBinding = getHoveredElementForBinding(
|
||||
{
|
||||
x: lastGlobalPoint[0],
|
||||
y: lastGlobalPoint[1],
|
||||
},
|
||||
elements,
|
||||
elementsMap,
|
||||
app.state.zoom,
|
||||
true,
|
||||
isElbowArrow(multiPointElement),
|
||||
);
|
||||
if (
|
||||
!lastCommittedPoint ||
|
||||
points[points.length - 1] !== lastCommittedPoint
|
||||
!hoveredElementForBinding &&
|
||||
(!lastCommittedPoint ||
|
||||
points[points.length - 1] !== lastCommittedPoint)
|
||||
) {
|
||||
mutateElement(multiPointElement, {
|
||||
points: multiPointElement.points.slice(0, -1),
|
||||
|
|
|
@ -5965,17 +5965,33 @@ class App extends React.Component<AppProps, AppState> {
|
|||
if (isPathALoop(points, this.state.zoom.value)) {
|
||||
setCursor(this.interactiveCanvas, CURSOR_TYPE.POINTER);
|
||||
}
|
||||
|
||||
const outlineGlobalPoint =
|
||||
LinearElementEditor.getOutlineAvoidingPointOrNull(
|
||||
multiElement,
|
||||
{
|
||||
x: scenePointerX,
|
||||
y: scenePointerY,
|
||||
},
|
||||
multiElement.points.length - 1,
|
||||
this,
|
||||
);
|
||||
|
||||
const nextPoint = outlineGlobalPoint
|
||||
? pointFrom<LocalPoint>(
|
||||
outlineGlobalPoint[0] - rx,
|
||||
outlineGlobalPoint[1] - ry,
|
||||
)
|
||||
: pointFrom<LocalPoint>(
|
||||
lastCommittedX + dxFromLastCommitted,
|
||||
lastCommittedY + dyFromLastCommitted,
|
||||
);
|
||||
|
||||
// update last uncommitted point
|
||||
mutateElement(
|
||||
multiElement,
|
||||
{
|
||||
points: [
|
||||
...points.slice(0, -1),
|
||||
pointFrom<LocalPoint>(
|
||||
lastCommittedX + dxFromLastCommitted,
|
||||
lastCommittedY + dyFromLastCommitted,
|
||||
),
|
||||
],
|
||||
points: [...points.slice(0, -1), nextPoint],
|
||||
},
|
||||
false,
|
||||
{
|
||||
|
@ -7715,10 +7731,26 @@ class App extends React.Component<AppProps, AppState> {
|
|||
}
|
||||
|
||||
const { x: rx, y: ry, lastCommittedPoint } = multiElement;
|
||||
const lastGlobalPoint = pointFrom<GlobalPoint>(
|
||||
rx + multiElement.points[multiElement.points.length - 1][0],
|
||||
ry + multiElement.points[multiElement.points.length - 1][1],
|
||||
);
|
||||
const hoveredElementForBinding = getHoveredElementForBinding(
|
||||
{
|
||||
x: lastGlobalPoint[0],
|
||||
y: lastGlobalPoint[1],
|
||||
},
|
||||
this.scene.getNonDeletedElements(),
|
||||
this.scene.getNonDeletedElementsMap(),
|
||||
this.state.zoom,
|
||||
true,
|
||||
isElbowArrow(multiElement),
|
||||
);
|
||||
|
||||
// clicking inside commit zone → finalize arrow
|
||||
if (
|
||||
multiElement.points.length > 1 &&
|
||||
!!hoveredElementForBinding ||
|
||||
(multiElement.points.length > 1 &&
|
||||
lastCommittedPoint &&
|
||||
pointDistance(
|
||||
pointFrom(
|
||||
|
@ -7726,7 +7758,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
pointerDownState.origin.y - ry,
|
||||
),
|
||||
lastCommittedPoint,
|
||||
) < LINE_CONFIRM_THRESHOLD
|
||||
) < LINE_CONFIRM_THRESHOLD)
|
||||
) {
|
||||
this.actionManager.executeAction(actionFinalize);
|
||||
return;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue