feat: cursor alignment when creating linear elements with shift pressed (#5518)
* feat: cursor alignment when creating linear elements * feat: apply cursor alignment to multi-point linear elements * refactor: rename size helper function
This commit is contained in:
parent
54c7ec416a
commit
865d29388c
@ -87,9 +87,9 @@ import {
|
|||||||
getDragOffsetXY,
|
getDragOffsetXY,
|
||||||
getElementWithTransformHandleType,
|
getElementWithTransformHandleType,
|
||||||
getNormalizedDimensions,
|
getNormalizedDimensions,
|
||||||
getPerfectElementSize,
|
|
||||||
getResizeArrowDirection,
|
getResizeArrowDirection,
|
||||||
getResizeOffsetXY,
|
getResizeOffsetXY,
|
||||||
|
getLockedLinearCursorAlignSize,
|
||||||
getTransformHandleTypeFromCoords,
|
getTransformHandleTypeFromCoords,
|
||||||
hitTest,
|
hitTest,
|
||||||
isHittingElementBoundingBoxWithoutHittingElement,
|
isHittingElementBoundingBoxWithoutHittingElement,
|
||||||
@ -2768,10 +2768,13 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
|
|
||||||
if (shouldRotateWithDiscreteAngle(event)) {
|
if (shouldRotateWithDiscreteAngle(event)) {
|
||||||
({ width: dxFromLastCommitted, height: dyFromLastCommitted } =
|
({ width: dxFromLastCommitted, height: dyFromLastCommitted } =
|
||||||
getPerfectElementSize(
|
getLockedLinearCursorAlignSize(
|
||||||
this.state.activeTool.type,
|
// actual coordinate of the last committed point
|
||||||
dxFromLastCommitted,
|
lastCommittedX + rx,
|
||||||
dyFromLastCommitted,
|
lastCommittedY + ry,
|
||||||
|
// cursor-grid coordinate
|
||||||
|
gridX,
|
||||||
|
gridY,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4241,10 +4244,11 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
let dy = gridY - draggingElement.y;
|
let dy = gridY - draggingElement.y;
|
||||||
|
|
||||||
if (shouldRotateWithDiscreteAngle(event) && points.length === 2) {
|
if (shouldRotateWithDiscreteAngle(event) && points.length === 2) {
|
||||||
({ width: dx, height: dy } = getPerfectElementSize(
|
({ width: dx, height: dy } = getLockedLinearCursorAlignSize(
|
||||||
this.state.activeTool.type,
|
draggingElement.x,
|
||||||
dx,
|
draggingElement.y,
|
||||||
dy,
|
pointerCoords.x,
|
||||||
|
pointerCoords.y,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@ export { textWysiwyg } from "./textWysiwyg";
|
|||||||
export { redrawTextBoundingBox } from "./textElement";
|
export { redrawTextBoundingBox } from "./textElement";
|
||||||
export {
|
export {
|
||||||
getPerfectElementSize,
|
getPerfectElementSize,
|
||||||
|
getLockedLinearCursorAlignSize,
|
||||||
isInvisiblySmallElement,
|
isInvisiblySmallElement,
|
||||||
resizePerfectLineForNWHandler,
|
resizePerfectLineForNWHandler,
|
||||||
getNormalizedDimensions,
|
getNormalizedDimensions,
|
||||||
|
@ -47,6 +47,46 @@ export const getPerfectElementSize = (
|
|||||||
return { width, height };
|
return { width, height };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getLockedLinearCursorAlignSize = (
|
||||||
|
originX: number,
|
||||||
|
originY: number,
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
) => {
|
||||||
|
let width = x - originX;
|
||||||
|
let height = y - originY;
|
||||||
|
|
||||||
|
const lockedAngle =
|
||||||
|
Math.round(Math.atan(height / width) / SHIFT_LOCKING_ANGLE) *
|
||||||
|
SHIFT_LOCKING_ANGLE;
|
||||||
|
|
||||||
|
if (lockedAngle === 0) {
|
||||||
|
height = 0;
|
||||||
|
} else if (lockedAngle === Math.PI / 2) {
|
||||||
|
width = 0;
|
||||||
|
} else {
|
||||||
|
// locked angle line, y = mx + b => mx - y + b = 0
|
||||||
|
const a1 = Math.tan(lockedAngle);
|
||||||
|
const b1 = -1;
|
||||||
|
const c1 = originY - a1 * originX;
|
||||||
|
|
||||||
|
// line through cursor, perpendicular to locked angle line
|
||||||
|
const a2 = -1 / a1;
|
||||||
|
const b2 = -1;
|
||||||
|
const c2 = y - a2 * x;
|
||||||
|
|
||||||
|
// intersection of the two lines above
|
||||||
|
const intersectX = Math.round((b1 * c2 - b2 * c1) / (a1 * b2 - a2 * b1));
|
||||||
|
const intersectY = Math.round((c1 * a2 - c2 * a1) / (a1 * b2 - a2 * b1));
|
||||||
|
|
||||||
|
// delta
|
||||||
|
width = intersectX - originX;
|
||||||
|
height = intersectY - originY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { width, height };
|
||||||
|
};
|
||||||
|
|
||||||
export const resizePerfectLineForNWHandler = (
|
export const resizePerfectLineForNWHandler = (
|
||||||
element: ExcalidrawElement,
|
element: ExcalidrawElement,
|
||||||
x: number,
|
x: number,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user