feat: add flipping when resizing multiple elements

This commit is contained in:
Alex Kim 2022-08-16 15:56:52 +05:00
parent b9ba407f96
commit a941173be4
No known key found for this signature in database
GPG key ID: CEE74CFA44D238D7

View file

@ -632,7 +632,17 @@ const resizeMultipleElements = (
? [midX, midY] ? [midX, midY]
: mapDirectionsToAnchors[direction]; : mapDirectionsToAnchors[direction];
const mapDirectionsToPointerSides: Record< const scale =
Math.max(
Math.abs(pointerX - anchorX) / (maxX - minX),
Math.abs(pointerY - anchorY) / (maxY - minY),
) * (shouldResizeFromCenter ? 2 : 1);
if (scale === 0) {
return;
}
const mapDirectionsToFlipConditions: Record<
typeof direction, typeof direction,
[x: boolean, y: boolean] [x: boolean, y: boolean]
> = { > = {
@ -642,37 +652,36 @@ const resizeMultipleElements = (
nw: [pointerX <= anchorX, pointerY <= anchorY], nw: [pointerX <= anchorX, pointerY <= anchorY],
}; };
// pointer side relative to anchor // to flip an element:
const [pointerSideX, pointerSideY] = mapDirectionsToPointerSides[ // 1. mirror x,y relative to the anchor over the x/y/both axis (flipFactor)
// 2. shift by the width/height/both (flipAdjust) or mirror points in case of
// linear/free draw element (hasPoints)
// 3. adjust the angle
const [flipFactorX, flipFactorY] = mapDirectionsToFlipConditions[
direction direction
].map((condition) => (condition ? 1 : -1)); ].map((condition) => (condition ? 1 : -1));
const isFlippedByX = flipFactorX < 0;
// stop resizing if a pointer is on the other side of selection const isFlippedByY = flipFactorY < 0;
if (pointerSideX < 0 && pointerSideY < 0) {
return;
}
const scale =
Math.max(
(pointerSideX * Math.abs(pointerX - anchorX)) / (maxX - minX),
(pointerSideY * Math.abs(pointerY - anchorY)) / (maxY - minY),
) * (shouldResizeFromCenter ? 2 : 1);
if (scale === 0) {
return;
}
targetElements.forEach((element) => { targetElements.forEach((element) => {
const width = element.orig.width * scale; const width = element.orig.width * scale;
const height = element.orig.height * scale; const height = element.orig.height * scale;
const x = anchorX + (element.orig.x - anchorX) * scale; const angle = element.orig.angle * flipFactorX * flipFactorY;
const y = anchorY + (element.orig.y - anchorY) * scale;
const hasPoints =
isLinearElement(element.orig) || isFreeDrawElement(element.orig);
const offsetX = element.orig.x - anchorX;
const offsetY = element.orig.y - anchorY;
const flipAdjustX = isFlippedByX && !hasPoints ? width : 0;
const flipAdjustY = isFlippedByY && !hasPoints ? height : 0;
const x = anchorX + flipFactorX * (offsetX * scale + flipAdjustX);
const y = anchorY + flipFactorY * (offsetY * scale + flipAdjustY);
// readjust points for linear & free draw elements // readjust points for linear & free draw elements
const rescaledPoints = rescalePointsInElement( const rescaledPoints = rescalePointsInElement(
element.orig, element.orig,
width, width * flipFactorX,
height, height * flipFactorY,
false, false,
); );
@ -681,6 +690,7 @@ const resizeMultipleElements = (
height: number; height: number;
x: number; x: number;
y: number; y: number;
angle: number;
points?: Point[]; points?: Point[];
fontSize?: number; fontSize?: number;
baseline?: number; baseline?: number;
@ -689,10 +699,15 @@ const resizeMultipleElements = (
height, height,
x, x,
y, y,
angle,
...rescaledPoints, ...rescaledPoints,
}; };
let boundTextUpdates: { fontSize: number; baseline: number } | null = null; let boundTextUpdates: {
angle: number;
fontSize: number;
baseline: number;
} | null = null;
const boundTextElement = getBoundTextElement(element.latest); const boundTextElement = getBoundTextElement(element.latest);
@ -715,6 +730,7 @@ const resizeMultipleElements = (
if (boundTextElement) { if (boundTextElement) {
boundTextUpdates = { boundTextUpdates = {
angle,
fontSize: textMeasurements.size, fontSize: textMeasurements.size,
baseline: textMeasurements.baseline, baseline: textMeasurements.baseline,
}; };