Procházet zdrojové kódy

fix: points not being normalized on single-elem resize (#5581)

David Luzar před 2 roky
rodič
revize
ad0c4c4c78

+ 3 - 1
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];

+ 1 - 0
src/element/newElement.ts

@@ -198,6 +198,7 @@ const getAdjustedDimensions = (
       element,
       nextWidth,
       nextHeight,
+      false,
     );
     const deltaX1 = (x1 - nextX1) / 2;
     const deltaY1 = (y1 - nextY1) / 2;

+ 14 - 2
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;

+ 27 - 1
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;
 };