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
8ac508af11
commit
8c9666b8ab
3 changed files with 92 additions and 25 deletions
|
@ -239,24 +239,23 @@ export class LinearElementEditor {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static getOutlineAvoidingPoint(
|
static getOutlineAvoidingPointOrNull(
|
||||||
element: NonDeleted<ExcalidrawLinearElement>,
|
element: NonDeleted<ExcalidrawLinearElement>,
|
||||||
coords: { x: number; y: number },
|
coords: { x: number; y: number },
|
||||||
pointIndex: number,
|
pointIndex: number,
|
||||||
app: AppClassProperties,
|
app: AppClassProperties,
|
||||||
): GlobalPoint {
|
) {
|
||||||
const elbowed = isElbowArrow(element);
|
|
||||||
const hoveredElement = getHoveredElementForBinding(
|
const hoveredElement = getHoveredElementForBinding(
|
||||||
coords,
|
coords,
|
||||||
app.scene.getNonDeletedElements(),
|
app.scene.getNonDeletedElements(),
|
||||||
app.scene.getNonDeletedElementsMap(),
|
app.scene.getNonDeletedElementsMap(),
|
||||||
app.state.zoom,
|
app.state.zoom,
|
||||||
true,
|
true,
|
||||||
elbowed,
|
isElbowArrow(element),
|
||||||
);
|
);
|
||||||
const p = pointFrom<GlobalPoint>(coords.x, coords.y);
|
|
||||||
|
|
||||||
if (hoveredElement) {
|
if (hoveredElement) {
|
||||||
|
const p = pointFrom<GlobalPoint>(coords.x, coords.y);
|
||||||
const newPoints = Array.from(element.points);
|
const newPoints = Array.from(element.points);
|
||||||
newPoints[pointIndex] = pointFrom<LocalPoint>(
|
newPoints[pointIndex] = pointFrom<LocalPoint>(
|
||||||
p[0] - element.x,
|
p[0] - element.x,
|
||||||
|
@ -274,7 +273,27 @@ export class LinearElementEditor {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return p;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -91,10 +91,26 @@ export const actionFinalize = register({
|
||||||
multiPointElement.type !== "freedraw" &&
|
multiPointElement.type !== "freedraw" &&
|
||||||
appState.lastPointerDownWith !== "touch"
|
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 (
|
if (
|
||||||
!lastCommittedPoint ||
|
!hoveredElementForBinding &&
|
||||||
points[points.length - 1] !== lastCommittedPoint
|
(!lastCommittedPoint ||
|
||||||
|
points[points.length - 1] !== lastCommittedPoint)
|
||||||
) {
|
) {
|
||||||
mutateElement(multiPointElement, {
|
mutateElement(multiPointElement, {
|
||||||
points: multiPointElement.points.slice(0, -1),
|
points: multiPointElement.points.slice(0, -1),
|
||||||
|
|
|
@ -5991,17 +5991,33 @@ class App extends React.Component<AppProps, AppState> {
|
||||||
if (isPathALoop(points, this.state.zoom.value)) {
|
if (isPathALoop(points, this.state.zoom.value)) {
|
||||||
setCursor(this.interactiveCanvas, CURSOR_TYPE.POINTER);
|
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
|
// update last uncommitted point
|
||||||
mutateElement(
|
mutateElement(
|
||||||
multiElement,
|
multiElement,
|
||||||
{
|
{
|
||||||
points: [
|
points: [...points.slice(0, -1), nextPoint],
|
||||||
...points.slice(0, -1),
|
|
||||||
pointFrom<LocalPoint>(
|
|
||||||
lastCommittedX + dxFromLastCommitted,
|
|
||||||
lastCommittedY + dyFromLastCommitted,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
{
|
{
|
||||||
|
@ -7751,18 +7767,34 @@ class App extends React.Component<AppProps, AppState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const { x: rx, y: ry, lastCommittedPoint } = multiElement;
|
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
|
// clicking inside commit zone → finalize arrow
|
||||||
if (
|
if (
|
||||||
multiElement.points.length > 1 &&
|
!!hoveredElementForBinding ||
|
||||||
lastCommittedPoint &&
|
(multiElement.points.length > 1 &&
|
||||||
pointDistance(
|
lastCommittedPoint &&
|
||||||
pointFrom(
|
pointDistance(
|
||||||
pointerDownState.origin.x - rx,
|
pointFrom(
|
||||||
pointerDownState.origin.y - ry,
|
pointerDownState.origin.x - rx,
|
||||||
),
|
pointerDownState.origin.y - ry,
|
||||||
lastCommittedPoint,
|
),
|
||||||
) < LINE_CONFIRM_THRESHOLD
|
lastCommittedPoint,
|
||||||
|
) < LINE_CONFIRM_THRESHOLD)
|
||||||
) {
|
) {
|
||||||
this.actionManager.executeAction(actionFinalize);
|
this.actionManager.executeAction(actionFinalize);
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue