From ad0c4c4c78f4e87e8eae96184a909bc9fec6e1ba Mon Sep 17 00:00:00 2001 From: David Luzar Date: Tue, 16 Aug 2022 21:51:43 +0200 Subject: [PATCH] fix: points not being normalized on single-elem resize (#5581) --- src/element/bounds.ts | 4 +++- src/element/newElement.ts | 1 + src/element/resizeElements.ts | 16 ++++++++++++++-- src/points.ts | 28 +++++++++++++++++++++++++++- 4 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/element/bounds.ts b/src/element/bounds.ts index a1e4197c..332e4be7 100644 --- a/src/element/bounds.ts +++ b/src/element/bounds.ts @@ -495,6 +495,7 @@ export const getResizedElementAbsoluteCoords = ( element: ExcalidrawElement, nextWidth: number, nextHeight: number, + normalizePoints: boolean, ): [number, number, number, number] => { if (!(isLinearElement(element) || isFreeDrawElement(element))) { return [ @@ -508,7 +509,8 @@ export const getResizedElementAbsoluteCoords = ( const points = rescalePoints( 0, nextWidth, - rescalePoints(1, nextHeight, element.points), + rescalePoints(1, nextHeight, element.points, normalizePoints), + normalizePoints, ); let bounds: [number, number, number, number]; diff --git a/src/element/newElement.ts b/src/element/newElement.ts index 234e06c3..2d6a12af 100644 --- a/src/element/newElement.ts +++ b/src/element/newElement.ts @@ -198,6 +198,7 @@ const getAdjustedDimensions = ( element, nextWidth, nextHeight, + false, ); const deltaX1 = (x1 - nextX1) / 2; const deltaY1 = (y1 - nextY1) / 2; diff --git a/src/element/resizeElements.ts b/src/element/resizeElements.ts index ac32a070..7de00afe 100644 --- a/src/element/resizeElements.ts +++ b/src/element/resizeElements.ts @@ -264,13 +264,15 @@ const rescalePointsInElement = ( element: NonDeletedExcalidrawElement, width: number, height: number, + normalizePoints: boolean, ) => isLinearElement(element) || isFreeDrawElement(element) ? { points: rescalePoints( 0, width, - rescalePoints(1, height, element.points), + rescalePoints(1, height, element.points, normalizePoints), + normalizePoints, ), } : {}; @@ -374,6 +376,7 @@ const resizeSingleTextElement = ( element, nextWidth, nextHeight, + false, ); const deltaX1 = (x1 - nextX1) / 2; const deltaY1 = (y1 - nextY1) / 2; @@ -415,6 +418,7 @@ export const resizeSingleElement = ( stateAtResizeStart, stateAtResizeStart.width, stateAtResizeStart.height, + true, ); const startTopLeft: Point = [x1, y1]; const startBottomRight: Point = [x2, y2]; @@ -432,6 +436,7 @@ export const resizeSingleElement = ( element, element.width, element.height, + true, ); const boundsCurrentWidth = esx2 - esx1; @@ -525,6 +530,7 @@ export const resizeSingleElement = ( stateAtResizeStart, eleNewWidth, eleNewHeight, + true, ); const newBoundsWidth = newBoundsX2 - newBoundsX1; const newBoundsHeight = newBoundsY2 - newBoundsY1; @@ -595,6 +601,7 @@ export const resizeSingleElement = ( stateAtResizeStart, eleNewWidth, eleNewHeight, + true, ); // For linear elements (x,y) are the coordinates of the first drawn point not the top-left corner // So we need to readjust (x,y) to be where the first point should be @@ -725,7 +732,12 @@ const resizeMultipleElements = ( const y = anchorY + (element.orig.y - anchorY) * scale; // readjust points for linear & free draw elements - const rescaledPoints = rescalePointsInElement(element.orig, width, height); + const rescaledPoints = rescalePointsInElement( + element.orig, + width, + height, + false, + ); const update: { width: number; diff --git a/src/points.ts b/src/points.ts index 311b8bbc..641a332d 100644 --- a/src/points.ts +++ b/src/points.ts @@ -14,6 +14,7 @@ export const rescalePoints = ( dimension: 0 | 1, newSize: number, points: readonly Point[], + normalize: boolean, ): Point[] => { const coordinates = points.map((point) => point[dimension]); const maxCoordinate = Math.max(...coordinates); @@ -21,10 +22,35 @@ export const rescalePoints = ( const size = maxCoordinate - minCoordinate; const scale = size === 0 ? 1 : newSize / size; - return points.map((point): Point => { + let nextMinCoordinate = Infinity; + + const scaledPoints = points.map((point): Point => { const newCoordinate = point[dimension] * scale; const newPoint = [...point]; newPoint[dimension] = newCoordinate; + if (newCoordinate < nextMinCoordinate) { + nextMinCoordinate = newCoordinate; + } return newPoint as unknown as Point; }); + + if (!normalize) { + return scaledPoints; + } + + if (scaledPoints.length === 2) { + // we don't translate two-point lines + return scaledPoints; + } + + const translation = minCoordinate - nextMinCoordinate; + + const nextPoints = scaledPoints.map( + (scaledPoint) => + scaledPoint.map((value, currentDimension) => { + return currentDimension === dimension ? value + translation : value; + }) as [number, number], + ); + + return nextPoints; };