|
@@ -1,12 +1,7 @@
|
|
import { MIN_FONT_SIZE, SHIFT_LOCKING_ANGLE } from "../constants";
|
|
import { MIN_FONT_SIZE, SHIFT_LOCKING_ANGLE } from "../constants";
|
|
import { rescalePoints } from "../points";
|
|
import { rescalePoints } from "../points";
|
|
|
|
|
|
-import {
|
|
|
|
- rotate,
|
|
|
|
- adjustXYWithRotation,
|
|
|
|
- centerPoint,
|
|
|
|
- rotatePoint,
|
|
|
|
-} from "../math";
|
|
|
|
|
|
+import { rotate, centerPoint, rotatePoint } from "../math";
|
|
import {
|
|
import {
|
|
ExcalidrawLinearElement,
|
|
ExcalidrawLinearElement,
|
|
ExcalidrawTextElement,
|
|
ExcalidrawTextElement,
|
|
@@ -23,7 +18,6 @@ import {
|
|
getCommonBounds,
|
|
getCommonBounds,
|
|
getResizedElementAbsoluteCoords,
|
|
getResizedElementAbsoluteCoords,
|
|
getCommonBoundingBox,
|
|
getCommonBoundingBox,
|
|
- getElementPointsCoords,
|
|
|
|
} from "./bounds";
|
|
} from "./bounds";
|
|
import {
|
|
import {
|
|
isArrowElement,
|
|
isArrowElement,
|
|
@@ -38,7 +32,6 @@ import { mutateElement } from "./mutateElement";
|
|
import { getFontString } from "../utils";
|
|
import { getFontString } from "../utils";
|
|
import { updateBoundElements } from "./binding";
|
|
import { updateBoundElements } from "./binding";
|
|
import {
|
|
import {
|
|
- TransformHandleType,
|
|
|
|
MaybeTransformHandleType,
|
|
MaybeTransformHandleType,
|
|
TransformHandleDirection,
|
|
TransformHandleDirection,
|
|
} from "./transformHandles";
|
|
} from "./transformHandles";
|
|
@@ -54,6 +47,7 @@ import {
|
|
getApproxMinLineHeight,
|
|
getApproxMinLineHeight,
|
|
} from "./textElement";
|
|
} from "./textElement";
|
|
import { LinearElementEditor } from "./linearElementEditor";
|
|
import { LinearElementEditor } from "./linearElementEditor";
|
|
|
|
+import { isInGroup } from "../groups";
|
|
|
|
|
|
export const normalizeAngle = (angle: number): number => {
|
|
export const normalizeAngle = (angle: number): number => {
|
|
if (angle < 0) {
|
|
if (angle < 0) {
|
|
@@ -133,18 +127,14 @@ export const transformElements = (
|
|
centerY,
|
|
centerY,
|
|
);
|
|
);
|
|
return true;
|
|
return true;
|
|
- } else if (
|
|
|
|
- transformHandleType === "nw" ||
|
|
|
|
- transformHandleType === "ne" ||
|
|
|
|
- transformHandleType === "sw" ||
|
|
|
|
- transformHandleType === "se"
|
|
|
|
- ) {
|
|
|
|
|
|
+ } else if (transformHandleType) {
|
|
resizeMultipleElements(
|
|
resizeMultipleElements(
|
|
originalElements,
|
|
originalElements,
|
|
selectedElements,
|
|
selectedElements,
|
|
elementsMap,
|
|
elementsMap,
|
|
transformHandleType,
|
|
transformHandleType,
|
|
shouldResizeFromCenter,
|
|
shouldResizeFromCenter,
|
|
|
|
+ shouldMaintainAspectRatio,
|
|
pointerX,
|
|
pointerX,
|
|
pointerY,
|
|
pointerY,
|
|
);
|
|
);
|
|
@@ -232,26 +222,6 @@ const measureFontSizeFromWidth = (
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
|
|
-const getSidesForTransformHandle = (
|
|
|
|
- transformHandleType: TransformHandleType,
|
|
|
|
- shouldResizeFromCenter: boolean,
|
|
|
|
-) => {
|
|
|
|
- return {
|
|
|
|
- n:
|
|
|
|
- /^(n|ne|nw)$/.test(transformHandleType) ||
|
|
|
|
- (shouldResizeFromCenter && /^(s|se|sw)$/.test(transformHandleType)),
|
|
|
|
- s:
|
|
|
|
- /^(s|se|sw)$/.test(transformHandleType) ||
|
|
|
|
- (shouldResizeFromCenter && /^(n|ne|nw)$/.test(transformHandleType)),
|
|
|
|
- w:
|
|
|
|
- /^(w|nw|sw)$/.test(transformHandleType) ||
|
|
|
|
- (shouldResizeFromCenter && /^(e|ne|se)$/.test(transformHandleType)),
|
|
|
|
- e:
|
|
|
|
- /^(e|ne|se)$/.test(transformHandleType) ||
|
|
|
|
- (shouldResizeFromCenter && /^(w|nw|sw)$/.test(transformHandleType)),
|
|
|
|
- };
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
const resizeSingleTextElement = (
|
|
const resizeSingleTextElement = (
|
|
element: NonDeleted<ExcalidrawTextElement>,
|
|
element: NonDeleted<ExcalidrawTextElement>,
|
|
elementsMap: ElementsMap,
|
|
elementsMap: ElementsMap,
|
|
@@ -260,9 +230,10 @@ const resizeSingleTextElement = (
|
|
pointerX: number,
|
|
pointerX: number,
|
|
pointerY: number,
|
|
pointerY: number,
|
|
) => {
|
|
) => {
|
|
- const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);
|
|
|
|
- const cx = (x1 + x2) / 2;
|
|
|
|
- const cy = (y1 + y2) / 2;
|
|
|
|
|
|
+ const [x1, y1, x2, y2, cx, cy] = getElementAbsoluteCoords(
|
|
|
|
+ element,
|
|
|
|
+ elementsMap,
|
|
|
|
+ );
|
|
// rotation pointer with reverse angle
|
|
// rotation pointer with reverse angle
|
|
const [rotatedX, rotatedY] = rotate(
|
|
const [rotatedX, rotatedY] = rotate(
|
|
pointerX,
|
|
pointerX,
|
|
@@ -271,33 +242,24 @@ const resizeSingleTextElement = (
|
|
cy,
|
|
cy,
|
|
-element.angle,
|
|
-element.angle,
|
|
);
|
|
);
|
|
- let scale: number;
|
|
|
|
- switch (transformHandleType) {
|
|
|
|
- case "se":
|
|
|
|
- scale = Math.max(
|
|
|
|
- (rotatedX - x1) / (x2 - x1),
|
|
|
|
- (rotatedY - y1) / (y2 - y1),
|
|
|
|
- );
|
|
|
|
- break;
|
|
|
|
- case "nw":
|
|
|
|
- scale = Math.max(
|
|
|
|
- (x2 - rotatedX) / (x2 - x1),
|
|
|
|
- (y2 - rotatedY) / (y2 - y1),
|
|
|
|
- );
|
|
|
|
- break;
|
|
|
|
- case "ne":
|
|
|
|
- scale = Math.max(
|
|
|
|
- (rotatedX - x1) / (x2 - x1),
|
|
|
|
- (y2 - rotatedY) / (y2 - y1),
|
|
|
|
- );
|
|
|
|
- break;
|
|
|
|
- case "sw":
|
|
|
|
- scale = Math.max(
|
|
|
|
- (x2 - rotatedX) / (x2 - x1),
|
|
|
|
- (rotatedY - y1) / (y2 - y1),
|
|
|
|
- );
|
|
|
|
- break;
|
|
|
|
|
|
+ let scaleX = 0;
|
|
|
|
+ let scaleY = 0;
|
|
|
|
+
|
|
|
|
+ if (transformHandleType.includes("e")) {
|
|
|
|
+ scaleX = (rotatedX - x1) / (x2 - x1);
|
|
}
|
|
}
|
|
|
|
+ if (transformHandleType.includes("w")) {
|
|
|
|
+ scaleX = (x2 - rotatedX) / (x2 - x1);
|
|
|
|
+ }
|
|
|
|
+ if (transformHandleType.includes("n")) {
|
|
|
|
+ scaleY = (y2 - rotatedY) / (y2 - y1);
|
|
|
|
+ }
|
|
|
|
+ if (transformHandleType.includes("s")) {
|
|
|
|
+ scaleY = (rotatedY - y1) / (y2 - y1);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const scale = Math.max(scaleX, scaleY);
|
|
|
|
+
|
|
if (scale > 0) {
|
|
if (scale > 0) {
|
|
const nextWidth = element.width * scale;
|
|
const nextWidth = element.width * scale;
|
|
const nextHeight = element.height * scale;
|
|
const nextHeight = element.height * scale;
|
|
@@ -305,32 +267,55 @@ const resizeSingleTextElement = (
|
|
if (metrics === null) {
|
|
if (metrics === null) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
- const [nextX1, nextY1, nextX2, nextY2] = getResizedElementAbsoluteCoords(
|
|
|
|
- element,
|
|
|
|
- nextWidth,
|
|
|
|
- nextHeight,
|
|
|
|
- false,
|
|
|
|
- );
|
|
|
|
- const deltaX1 = (x1 - nextX1) / 2;
|
|
|
|
- const deltaY1 = (y1 - nextY1) / 2;
|
|
|
|
- const deltaX2 = (x2 - nextX2) / 2;
|
|
|
|
- const deltaY2 = (y2 - nextY2) / 2;
|
|
|
|
- const [nextElementX, nextElementY] = adjustXYWithRotation(
|
|
|
|
- getSidesForTransformHandle(transformHandleType, shouldResizeFromCenter),
|
|
|
|
- element.x,
|
|
|
|
- element.y,
|
|
|
|
- element.angle,
|
|
|
|
- deltaX1,
|
|
|
|
- deltaY1,
|
|
|
|
- deltaX2,
|
|
|
|
- deltaY2,
|
|
|
|
- );
|
|
|
|
|
|
+
|
|
|
|
+ const startTopLeft = [x1, y1];
|
|
|
|
+ const startBottomRight = [x2, y2];
|
|
|
|
+ const startCenter = [cx, cy];
|
|
|
|
+
|
|
|
|
+ let newTopLeft = [x1, y1] as [number, number];
|
|
|
|
+ if (["n", "w", "nw"].includes(transformHandleType)) {
|
|
|
|
+ newTopLeft = [
|
|
|
|
+ startBottomRight[0] - Math.abs(nextWidth),
|
|
|
|
+ startBottomRight[1] - Math.abs(nextHeight),
|
|
|
|
+ ];
|
|
|
|
+ }
|
|
|
|
+ if (transformHandleType === "ne") {
|
|
|
|
+ const bottomLeft = [startTopLeft[0], startBottomRight[1]];
|
|
|
|
+ newTopLeft = [bottomLeft[0], bottomLeft[1] - Math.abs(nextHeight)];
|
|
|
|
+ }
|
|
|
|
+ if (transformHandleType === "sw") {
|
|
|
|
+ const topRight = [startBottomRight[0], startTopLeft[1]];
|
|
|
|
+ newTopLeft = [topRight[0] - Math.abs(nextWidth), topRight[1]];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (["s", "n"].includes(transformHandleType)) {
|
|
|
|
+ newTopLeft[0] = startCenter[0] - nextWidth / 2;
|
|
|
|
+ }
|
|
|
|
+ if (["e", "w"].includes(transformHandleType)) {
|
|
|
|
+ newTopLeft[1] = startCenter[1] - nextHeight / 2;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (shouldResizeFromCenter) {
|
|
|
|
+ newTopLeft[0] = startCenter[0] - Math.abs(nextWidth) / 2;
|
|
|
|
+ newTopLeft[1] = startCenter[1] - Math.abs(nextHeight) / 2;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const angle = element.angle;
|
|
|
|
+ const rotatedTopLeft = rotatePoint(newTopLeft, [cx, cy], angle);
|
|
|
|
+ const newCenter: Point = [
|
|
|
|
+ newTopLeft[0] + Math.abs(nextWidth) / 2,
|
|
|
|
+ newTopLeft[1] + Math.abs(nextHeight) / 2,
|
|
|
|
+ ];
|
|
|
|
+ const rotatedNewCenter = rotatePoint(newCenter, [cx, cy], angle);
|
|
|
|
+ newTopLeft = rotatePoint(rotatedTopLeft, rotatedNewCenter, -angle);
|
|
|
|
+ const [nextX, nextY] = newTopLeft;
|
|
|
|
+
|
|
mutateElement(element, {
|
|
mutateElement(element, {
|
|
fontSize: metrics.size,
|
|
fontSize: metrics.size,
|
|
width: nextWidth,
|
|
width: nextWidth,
|
|
height: nextHeight,
|
|
height: nextHeight,
|
|
- x: nextElementX,
|
|
|
|
- y: nextElementY,
|
|
|
|
|
|
+ x: nextX,
|
|
|
|
+ y: nextY,
|
|
});
|
|
});
|
|
}
|
|
}
|
|
};
|
|
};
|
|
@@ -636,8 +621,9 @@ export const resizeMultipleElements = (
|
|
originalElements: PointerDownState["originalElements"],
|
|
originalElements: PointerDownState["originalElements"],
|
|
selectedElements: readonly NonDeletedExcalidrawElement[],
|
|
selectedElements: readonly NonDeletedExcalidrawElement[],
|
|
elementsMap: ElementsMap,
|
|
elementsMap: ElementsMap,
|
|
- transformHandleType: "nw" | "ne" | "sw" | "se",
|
|
|
|
|
|
+ transformHandleType: TransformHandleDirection,
|
|
shouldResizeFromCenter: boolean,
|
|
shouldResizeFromCenter: boolean,
|
|
|
|
+ shouldMaintainAspectRatio: boolean,
|
|
pointerX: number,
|
|
pointerX: number,
|
|
pointerY: number,
|
|
pointerY: number,
|
|
) => {
|
|
) => {
|
|
@@ -691,43 +677,80 @@ export const resizeMultipleElements = (
|
|
const { minX, minY, maxX, maxY, midX, midY } = getCommonBoundingBox(
|
|
const { minX, minY, maxX, maxY, midX, midY } = getCommonBoundingBox(
|
|
targetElements.map(({ orig }) => orig).concat(boundTextElements),
|
|
targetElements.map(({ orig }) => orig).concat(boundTextElements),
|
|
);
|
|
);
|
|
-
|
|
|
|
- // const originalHeight = maxY - minY;
|
|
|
|
- // const originalWidth = maxX - minX;
|
|
|
|
|
|
+ const width = maxX - minX;
|
|
|
|
+ const height = maxY - minY;
|
|
|
|
|
|
const direction = transformHandleType;
|
|
const direction = transformHandleType;
|
|
|
|
|
|
- const mapDirectionsToAnchors: Record<typeof direction, Point> = {
|
|
|
|
|
|
+ const anchorsMap: Record<TransformHandleDirection, Point> = {
|
|
ne: [minX, maxY],
|
|
ne: [minX, maxY],
|
|
se: [minX, minY],
|
|
se: [minX, minY],
|
|
sw: [maxX, minY],
|
|
sw: [maxX, minY],
|
|
nw: [maxX, maxY],
|
|
nw: [maxX, maxY],
|
|
|
|
+ e: [minX, minY + height / 2],
|
|
|
|
+ w: [maxX, minY + height / 2],
|
|
|
|
+ n: [minX + width / 2, maxY],
|
|
|
|
+ s: [minX + width / 2, minY],
|
|
};
|
|
};
|
|
|
|
|
|
// anchor point must be on the opposite side of the dragged selection handle
|
|
// anchor point must be on the opposite side of the dragged selection handle
|
|
// or be the center of the selection if shouldResizeFromCenter
|
|
// or be the center of the selection if shouldResizeFromCenter
|
|
const [anchorX, anchorY]: Point = shouldResizeFromCenter
|
|
const [anchorX, anchorY]: Point = shouldResizeFromCenter
|
|
? [midX, midY]
|
|
? [midX, midY]
|
|
- : mapDirectionsToAnchors[direction];
|
|
|
|
|
|
+ : anchorsMap[direction];
|
|
|
|
+
|
|
|
|
+ const resizeFromCenterScale = shouldResizeFromCenter ? 2 : 1;
|
|
|
|
|
|
const scale =
|
|
const scale =
|
|
Math.max(
|
|
Math.max(
|
|
- Math.abs(pointerX - anchorX) / (maxX - minX) || 0,
|
|
|
|
- Math.abs(pointerY - anchorY) / (maxY - minY) || 0,
|
|
|
|
- ) * (shouldResizeFromCenter ? 2 : 1);
|
|
|
|
|
|
+ Math.abs(pointerX - anchorX) / width || 0,
|
|
|
|
+ Math.abs(pointerY - anchorY) / height || 0,
|
|
|
|
+ ) * resizeFromCenterScale;
|
|
|
|
|
|
if (scale === 0) {
|
|
if (scale === 0) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- const mapDirectionsToPointerPositions: Record<
|
|
|
|
- typeof direction,
|
|
|
|
|
|
+ let scaleX =
|
|
|
|
+ direction.includes("e") || direction.includes("w")
|
|
|
|
+ ? (Math.abs(pointerX - anchorX) / width) * resizeFromCenterScale
|
|
|
|
+ : 1;
|
|
|
|
+ let scaleY =
|
|
|
|
+ direction.includes("n") || direction.includes("s")
|
|
|
|
+ ? (Math.abs(pointerY - anchorY) / height) * resizeFromCenterScale
|
|
|
|
+ : 1;
|
|
|
|
+
|
|
|
|
+ const keepAspectRatio =
|
|
|
|
+ shouldMaintainAspectRatio ||
|
|
|
|
+ targetElements.some(
|
|
|
|
+ (item) =>
|
|
|
|
+ item.latest.angle !== 0 ||
|
|
|
|
+ isTextElement(item.latest) ||
|
|
|
|
+ isInGroup(item.latest),
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ if (keepAspectRatio) {
|
|
|
|
+ scaleX = scale;
|
|
|
|
+ scaleY = scale;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const flipConditionsMap: Record<
|
|
|
|
+ TransformHandleDirection,
|
|
|
|
+ // Condition for which we should flip or not flip the selected elements
|
|
|
|
+ // - when evaluated to `true`, we flip
|
|
|
|
+ // - therefore, setting it to always `false` means we do not flip (in that direction) at all
|
|
[x: boolean, y: boolean]
|
|
[x: boolean, y: boolean]
|
|
> = {
|
|
> = {
|
|
- ne: [pointerX >= anchorX, pointerY <= anchorY],
|
|
|
|
- se: [pointerX >= anchorX, pointerY >= anchorY],
|
|
|
|
- sw: [pointerX <= anchorX, pointerY >= anchorY],
|
|
|
|
- nw: [pointerX <= anchorX, pointerY <= anchorY],
|
|
|
|
|
|
+ ne: [pointerX < anchorX, pointerY > anchorY],
|
|
|
|
+ se: [pointerX < anchorX, pointerY < anchorY],
|
|
|
|
+ sw: [pointerX > anchorX, pointerY < anchorY],
|
|
|
|
+ nw: [pointerX > anchorX, pointerY > anchorY],
|
|
|
|
+ // e.g. when resizing from the "e" side, we do not need to consider changes in the `y` direction
|
|
|
|
+ // and therefore, we do not need to flip in the `y` direction at all
|
|
|
|
+ e: [pointerX < anchorX, false],
|
|
|
|
+ w: [pointerX > anchorX, false],
|
|
|
|
+ n: [false, pointerY > anchorY],
|
|
|
|
+ s: [false, pointerY < anchorY],
|
|
};
|
|
};
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -738,9 +761,9 @@ export const resizeMultipleElements = (
|
|
* mirror points in the case of linear & freedraw elemenets
|
|
* mirror points in the case of linear & freedraw elemenets
|
|
* 3. adjust element angle
|
|
* 3. adjust element angle
|
|
*/
|
|
*/
|
|
- const [flipFactorX, flipFactorY] = mapDirectionsToPointerPositions[
|
|
|
|
- direction
|
|
|
|
- ].map((condition) => (condition ? 1 : -1));
|
|
|
|
|
|
+ const [flipFactorX, flipFactorY] = flipConditionsMap[direction].map(
|
|
|
|
+ (condition) => (condition ? -1 : 1),
|
|
|
|
+ );
|
|
const isFlippedByX = flipFactorX < 0;
|
|
const isFlippedByX = flipFactorX < 0;
|
|
const isFlippedByY = flipFactorY < 0;
|
|
const isFlippedByY = flipFactorY < 0;
|
|
|
|
|
|
@@ -762,8 +785,8 @@ export const resizeMultipleElements = (
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
|
|
- const width = orig.width * scale;
|
|
|
|
- const height = orig.height * scale;
|
|
|
|
|
|
+ const width = orig.width * scaleX;
|
|
|
|
+ const height = orig.height * scaleY;
|
|
const angle = normalizeAngle(orig.angle * flipFactorX * flipFactorY);
|
|
const angle = normalizeAngle(orig.angle * flipFactorX * flipFactorY);
|
|
|
|
|
|
const isLinearOrFreeDraw = isLinearElement(orig) || isFreeDrawElement(orig);
|
|
const isLinearOrFreeDraw = isLinearElement(orig) || isFreeDrawElement(orig);
|
|
@@ -771,8 +794,8 @@ export const resizeMultipleElements = (
|
|
const offsetY = orig.y - anchorY;
|
|
const offsetY = orig.y - anchorY;
|
|
const shiftX = isFlippedByX && !isLinearOrFreeDraw ? width : 0;
|
|
const shiftX = isFlippedByX && !isLinearOrFreeDraw ? width : 0;
|
|
const shiftY = isFlippedByY && !isLinearOrFreeDraw ? height : 0;
|
|
const shiftY = isFlippedByY && !isLinearOrFreeDraw ? height : 0;
|
|
- const x = anchorX + flipFactorX * (offsetX * scale + shiftX);
|
|
|
|
- const y = anchorY + flipFactorY * (offsetY * scale + shiftY);
|
|
|
|
|
|
+ const x = anchorX + flipFactorX * (offsetX * scaleX + shiftX);
|
|
|
|
+ const y = anchorY + flipFactorY * (offsetY * scaleY + shiftY);
|
|
|
|
|
|
const rescaledPoints = rescalePointsInElement(
|
|
const rescaledPoints = rescalePointsInElement(
|
|
orig,
|
|
orig,
|
|
@@ -790,40 +813,10 @@ export const resizeMultipleElements = (
|
|
...rescaledPoints,
|
|
...rescaledPoints,
|
|
};
|
|
};
|
|
|
|
|
|
- if (isImageElement(orig) && targetElements.length === 1) {
|
|
|
|
|
|
+ if (isImageElement(orig)) {
|
|
update.scale = [orig.scale[0] * flipFactorX, orig.scale[1] * flipFactorY];
|
|
update.scale = [orig.scale[0] * flipFactorX, orig.scale[1] * flipFactorY];
|
|
}
|
|
}
|
|
|
|
|
|
- if (isLinearElement(orig) && (isFlippedByX || isFlippedByY)) {
|
|
|
|
- const origBounds = getElementPointsCoords(orig, orig.points);
|
|
|
|
- const newBounds = getElementPointsCoords(
|
|
|
|
- { ...orig, x, y },
|
|
|
|
- rescaledPoints.points!,
|
|
|
|
- );
|
|
|
|
- const origXY = [orig.x, orig.y];
|
|
|
|
- const newXY = [x, y];
|
|
|
|
-
|
|
|
|
- const linearShift = (axis: "x" | "y") => {
|
|
|
|
- const i = axis === "x" ? 0 : 1;
|
|
|
|
- return (
|
|
|
|
- (newBounds[i + 2] -
|
|
|
|
- newXY[i] -
|
|
|
|
- (origXY[i] - origBounds[i]) * scale +
|
|
|
|
- (origBounds[i + 2] - origXY[i]) * scale -
|
|
|
|
- (newXY[i] - newBounds[i])) /
|
|
|
|
- 2
|
|
|
|
- );
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- if (isFlippedByX) {
|
|
|
|
- update.x -= linearShift("x");
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (isFlippedByY) {
|
|
|
|
- update.y -= linearShift("y");
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
if (isTextElement(orig)) {
|
|
if (isTextElement(orig)) {
|
|
const metrics = measureFontSizeFromWidth(orig, elementsMap, width);
|
|
const metrics = measureFontSizeFromWidth(orig, elementsMap, width);
|
|
if (!metrics) {
|
|
if (!metrics) {
|
|
@@ -837,11 +830,15 @@ export const resizeMultipleElements = (
|
|
) as ExcalidrawTextElementWithContainer | undefined;
|
|
) as ExcalidrawTextElementWithContainer | undefined;
|
|
|
|
|
|
if (boundTextElement) {
|
|
if (boundTextElement) {
|
|
- const newFontSize = boundTextElement.fontSize * scale;
|
|
|
|
- if (newFontSize < MIN_FONT_SIZE) {
|
|
|
|
- return;
|
|
|
|
|
|
+ if (keepAspectRatio) {
|
|
|
|
+ const newFontSize = boundTextElement.fontSize * scale;
|
|
|
|
+ if (newFontSize < MIN_FONT_SIZE) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ update.boundTextFontSize = newFontSize;
|
|
|
|
+ } else {
|
|
|
|
+ update.boundTextFontSize = boundTextElement.fontSize;
|
|
}
|
|
}
|
|
- update.boundTextFontSize = newFontSize;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
elementsAndUpdates.push({
|
|
elementsAndUpdates.push({
|