From d29fd62e417b8cb73d1d5dc3e207735046401491 Mon Sep 17 00:00:00 2001 From: David Luzar <5153846+dwelle@users.noreply.github.com> Date: Sun, 1 Feb 2026 10:45:04 +0100 Subject: [PATCH] fix(editor): crop editor cursor drift (#10727) * fix(editor): do not scale cropping editor pointer offsets * fix lint * fix more lint * fix drift related to image canvas scale --- packages/excalidraw/components/App.tsx | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index bbd748d8a8..fa9a02b492 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -11,7 +11,6 @@ import { pointDistance, vector, pointRotateRads, - vectorScale, vectorFromPoint, vectorSubtract, vectorDot, @@ -255,6 +254,7 @@ import { handleFocusPointPointerDown, handleFocusPointPointerUp, maybeHandleArrowPointlikeDrag, + getUncroppedWidthAndHeight, } from "@excalidraw/element"; import type { GlobalPoint, LocalPoint, Radians } from "@excalidraw/math"; @@ -9341,14 +9341,21 @@ class App extends React.Component { this.imageCache.get(croppingElement.fileId)?.image; if (image && !(image instanceof Promise)) { - const instantDragOffset = vectorScale( - vector( - pointerCoords.x - lastPointerCoords.x, - pointerCoords.y - lastPointerCoords.y, - ), - Math.max(this.state.zoom.value, 2), + const uncroppedSize = + getUncroppedWidthAndHeight(croppingElement); + const instantDragOffset = vector( + pointerCoords.x - lastPointerCoords.x, + pointerCoords.y - lastPointerCoords.y, ); + // to reduce cursor:image drift, we need to take into account + // the canvas image element scaling so we can accurately + // track the pixels on movement + instantDragOffset[0] *= + image.naturalWidth / uncroppedSize.width; + instantDragOffset[1] *= + image.naturalHeight / uncroppedSize.height; + const [x1, y1, x2, y2, cx, cy] = getElementAbsoluteCoords( croppingElement, elementsMap,