diff --git a/packages/element/src/bounds.ts b/packages/element/src/bounds.ts index 6b190de1b7..0f3970db80 100644 --- a/packages/element/src/bounds.ts +++ b/packages/element/src/bounds.ts @@ -42,6 +42,7 @@ import { isBoundToContainer, isFreeDrawElement, isLinearElement, + isLineElement, isTextElement, } from "./typeChecks"; @@ -321,19 +322,42 @@ export const getElementLineSegments = ( if (shape.type === "polycurve") { const curves = shape.data; - const points = curves - .map((curve) => pointsOnBezierCurves(curve, 10)) - .flat(); - let i = 0; + const pointsOnCurves = curves.map((curve) => + pointsOnBezierCurves(curve, 10), + ); + const segments: LineSegment[] = []; - while (i < points.length - 1) { - segments.push( - lineSegment( - pointFrom(points[i][0], points[i][1]), - pointFrom(points[i + 1][0], points[i + 1][1]), - ), - ); - i++; + + if ( + (isLineElement(element) && !element.polygon) || + isArrowElement(element) + ) { + for (const points of pointsOnCurves) { + let i = 0; + + while (i < points.length - 1) { + segments.push( + lineSegment( + pointFrom(points[i][0], points[i][1]), + pointFrom(points[i + 1][0], points[i + 1][1]), + ), + ); + i++; + } + } + } else { + const points = pointsOnCurves.flat(); + let i = 0; + + while (i < points.length - 1) { + segments.push( + lineSegment( + pointFrom(points[i][0], points[i][1]), + pointFrom(points[i + 1][0], points[i + 1][1]), + ), + ); + i++; + } } return segments; diff --git a/packages/excalidraw/eraser/index.ts b/packages/excalidraw/eraser/index.ts index 8d09b1aafc..d587bb3811 100644 --- a/packages/excalidraw/eraser/index.ts +++ b/packages/excalidraw/eraser/index.ts @@ -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)