fix: Arrow eraser precision & lasso arrow selection

This commit is contained in:
Mark Tolmacs
2025-09-22 16:44:34 +02:00
parent f55ecb96cc
commit 54ca52e063
2 changed files with 38 additions and 9 deletions

View File

@@ -42,6 +42,7 @@ import {
isBoundToContainer,
isFreeDrawElement,
isLinearElement,
isLineElement,
isTextElement,
} from "./typeChecks";
@@ -324,9 +325,28 @@ export const getElementLineSegments = (
const points = curves
.map((curve) => pointsOnBezierCurves(curve, 10))
.flat();
let i = 0;
const segments: LineSegment<GlobalPoint>[] = [];
let i = 0;
while (i < points.length - 1) {
const p1 = pointFrom(points[i + 1][0], points[i][1]);
const p2 = pointFrom(points[i][0], points[i + 1][1]);
const alignsWithStart = pointDistance(p1, points[0] as GlobalPoint) < 1;
const alignsWithEnd =
pointDistance(p2, points[points.length - 1] as GlobalPoint) < 1;
// Avoid closing the polycurve for non-polygon lines and arrows
if (
((isLineElement(element) && !element.polygon) ||
isArrowElement(element)) &&
alignsWithStart &&
alignsWithEnd
) {
i++;
continue;
}
segments.push(
lineSegment(
pointFrom(points[i][0], points[i][1]),

View File

@@ -2,10 +2,10 @@ import { arrayToMap, easeOut, THEME } from "@excalidraw/common";
import {
computeBoundTextPosition,
distanceToElement,
doBoundsIntersect,
getBoundTextElement,
getElementBounds,
getElementLineSegments,
getFreedrawOutlineAsSegments,
getFreedrawOutlinePoints,
intersectElementWithLineSegment,
@@ -265,19 +265,28 @@ const eraserTest = (
}
return false;
} else if (
isArrowElement(element) ||
(isLineElement(element) && !element.polygon)
) {
}
const boundTextElement = getBoundTextElement(element, elementsMap);
if (isArrowElement(element) || (isLineElement(element) && !element.polygon)) {
const tolerance = Math.max(
element.strokeWidth,
(element.strokeWidth * 2) / zoom,
);
return distanceToElement(element, elementsMap, lastPoint) <= tolerance;
}
// If the eraser movement is so fast that a large distance is covered
// between the last two points, the distanceToElement miss, so we test
// agaist each segment of the linear element
const segments = getElementLineSegments(element, elementsMap);
for (const seg of segments) {
if (lineSegmentsDistance(seg, pathSegment) <= tolerance) {
return true;
}
}
const boundTextElement = getBoundTextElement(element, elementsMap);
return false;
}
return (
intersectElementWithLineSegment(element, elementsMap, pathSegment, 0, true)