Fix resize logic (partly) (#1475)

This commit is contained in:
Daishi Kato 2020-04-27 17:30:19 +09:00 committed by GitHub
parent 4824f9e1d4
commit da1031aeb4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 26 deletions

View File

@ -140,7 +140,7 @@ export const resizeElements = (
const handleOffset = 4 / appState.zoom; // XXX import constant const handleOffset = 4 / appState.zoom; // XXX import constant
const dashedLinePadding = 4 / appState.zoom; // XXX import constant const dashedLinePadding = 4 / appState.zoom; // XXX import constant
const offsetPointer = handleOffset + dashedLinePadding; const offsetPointer = handleOffset + dashedLinePadding;
const minSize = handleOffset * 4; const minSize = 0;
if (selectedElements.length === 1) { if (selectedElements.length === 1) {
const [element] = selectedElements; const [element] = selectedElements;
if (resizeHandle === "rotation") { if (resizeHandle === "rotation") {
@ -182,15 +182,17 @@ export const resizeElements = (
lastY, lastY,
); );
} else if (resizeHandle) { } else if (resizeHandle) {
const [x1, y1] = getElementAbsoluteCoords(element); const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
const resized = resizeXYWidthHightWithRotation( const resized = resizeXYWidthHightWithRotation(
resizeHandle, resizeHandle,
x1, x1,
y1, y1,
x2,
y2,
element.width, element.width,
element.height, element.height,
x1 - element.x, element.x,
y1 - element.y, element.y,
element.angle, element.angle,
xPointer, xPointer,
yPointer, yPointer,
@ -198,7 +200,10 @@ export const resizeElements = (
getResizeWithSidesSameLengthKey(event), getResizeWithSidesSameLengthKey(event),
getResizeCenterPointKey(event), getResizeCenterPointKey(event),
); );
if (resized.width !== 0 && resized.height !== 0) { if (
Math.abs(resized.width) > minSize &&
Math.abs(resized.height) > minSize
) {
mutateElement(element, { mutateElement(element, {
...resized, ...resized,
...(isLinearElement(element) ...(isLinearElement(element)

View File

@ -46,7 +46,7 @@ export function rotate(
x2: number, x2: number,
y2: number, y2: number,
angle: number, angle: number,
) { ): [number, number] {
// 𝑎𝑥=(𝑎𝑥𝑐𝑥)cos𝜃(𝑎𝑦𝑐𝑦)sin𝜃+𝑐𝑥 // 𝑎𝑥=(𝑎𝑥𝑐𝑥)cos𝜃(𝑎𝑦𝑐𝑦)sin𝜃+𝑐𝑥
// 𝑎𝑦=(𝑎𝑥𝑐𝑥)sin𝜃+(𝑎𝑦𝑐𝑦)cos𝜃+𝑐𝑦. // 𝑎𝑦=(𝑎𝑥𝑐𝑥)sin𝜃+(𝑎𝑦𝑐𝑦)cos𝜃+𝑐𝑦.
// https://math.stackexchange.com/questions/2204520/how-do-i-rotate-a-line-segment-in-a-specific-point-on-the-line // https://math.stackexchange.com/questions/2204520/how-do-i-rotate-a-line-segment-in-a-specific-point-on-the-line
@ -67,8 +67,6 @@ const adjustXYWithRotation = (
) => { ) => {
const cos = Math.cos(angle); const cos = Math.cos(angle);
const sin = Math.sin(angle); const sin = Math.sin(angle);
deltaX /= 2;
deltaY /= 2;
if (side === "e" || side === "ne" || side === "se") { if (side === "e" || side === "ne" || side === "se") {
if (isResizeFromCenter) { if (isResizeFromCenter) {
x += deltaX; x += deltaX;
@ -106,12 +104,14 @@ const adjustXYWithRotation = (
export const resizeXYWidthHightWithRotation = ( export const resizeXYWidthHightWithRotation = (
side: "n" | "s" | "w" | "e" | "nw" | "ne" | "sw" | "se", side: "n" | "s" | "w" | "e" | "nw" | "ne" | "sw" | "se",
x: number, x1: number,
y: number, y1: number,
width: number, x2: number,
height: number, y2: number,
offsetX: number, elementWidth: number,
offsetY: number, elementHeight: number,
elementX: number,
elementY: number,
angle: number, angle: number,
xPointer: number, xPointer: number,
yPointer: number, yPointer: number,
@ -120,43 +120,56 @@ export const resizeXYWidthHightWithRotation = (
isResizeFromCenter: boolean, isResizeFromCenter: boolean,
) => { ) => {
// center point for rotation // center point for rotation
const cx = x + width / 2; const cx = (x1 + x2) / 2;
const cy = y + height / 2; const cy = (y1 + y2) / 2;
// rotation with current angle // rotation with current angle
const [rotatedX, rotatedY] = rotate(xPointer, yPointer, cx, cy, -angle); const [rotatedX, rotatedY] = rotate(xPointer, yPointer, cx, cy, -angle);
// XXX this might be slow with closure
const adjustWithOffsetPointer = (w: number) => {
if (w > offsetPointer) {
return w - offsetPointer;
} else if (w < -offsetPointer) {
return w + offsetPointer;
}
return 0;
};
let scaleX = 1; let scaleX = 1;
let scaleY = 1; let scaleY = 1;
if (side === "e" || side === "ne" || side === "se") { if (side === "e" || side === "ne" || side === "se") {
scaleX = (rotatedX - offsetPointer - x) / width; scaleX = adjustWithOffsetPointer(rotatedX - x1) / (x2 - x1);
} }
if (side === "s" || side === "sw" || side === "se") { if (side === "s" || side === "sw" || side === "se") {
scaleY = (rotatedY - offsetPointer - y) / height; scaleY = adjustWithOffsetPointer(rotatedY - y1) / (y2 - y1);
} }
if (side === "w" || side === "nw" || side === "sw") { if (side === "w" || side === "nw" || side === "sw") {
scaleX = (x + width - offsetPointer - rotatedX) / width; scaleX = adjustWithOffsetPointer(x2 - rotatedX) / (x2 - x1);
} }
if (side === "n" || side === "nw" || side === "ne") { if (side === "n" || side === "nw" || side === "ne") {
scaleY = (y + height - offsetPointer - rotatedY) / height; scaleY = adjustWithOffsetPointer(y2 - rotatedY) / (y2 - y1);
} }
let nextWidth = width * scaleX; let nextWidth = elementWidth * scaleX;
let nextHeight = height * scaleY; let nextHeight = elementHeight * scaleY;
if (sidesWithSameLength) { if (sidesWithSameLength) {
nextWidth = nextHeight = Math.max(nextWidth, nextHeight); nextWidth = nextHeight = Math.max(nextWidth, nextHeight);
} }
const deltaX = (elementWidth - nextWidth) / 2;
const deltaY = (elementHeight - nextHeight) / 2;
return { return {
width: nextWidth, width: nextWidth,
height: nextHeight, height: nextHeight,
...adjustXYWithRotation( ...adjustXYWithRotation(
side, side,
x - offsetX, elementX,
y - offsetY, elementY,
angle, angle,
width - nextWidth, deltaX,
height - nextHeight, deltaY,
isResizeFromCenter, isResizeFromCenter,
), ),
}; };