Function implemented
This commit is contained in:
parent
14d512f321
commit
001df5bade
@ -117,6 +117,7 @@ export class LinearElementEditor {
|
|||||||
public readonly hoverPointIndex: number;
|
public readonly hoverPointIndex: number;
|
||||||
public readonly segmentMidPointHoveredCoords: GlobalPoint | null;
|
public readonly segmentMidPointHoveredCoords: GlobalPoint | null;
|
||||||
public readonly elbowed: boolean;
|
public readonly elbowed: boolean;
|
||||||
|
public readonly customLineAngle: number | null;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
element: NonDeleted<ExcalidrawLinearElement>,
|
element: NonDeleted<ExcalidrawLinearElement>,
|
||||||
@ -150,6 +151,7 @@ export class LinearElementEditor {
|
|||||||
this.hoverPointIndex = -1;
|
this.hoverPointIndex = -1;
|
||||||
this.segmentMidPointHoveredCoords = null;
|
this.segmentMidPointHoveredCoords = null;
|
||||||
this.elbowed = isElbowArrow(element) && element.elbowed;
|
this.elbowed = isElbowArrow(element) && element.elbowed;
|
||||||
|
this.customLineAngle = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@ -253,6 +255,7 @@ export class LinearElementEditor {
|
|||||||
const { elementId } = linearElementEditor;
|
const { elementId } = linearElementEditor;
|
||||||
const elementsMap = scene.getNonDeletedElementsMap();
|
const elementsMap = scene.getNonDeletedElementsMap();
|
||||||
const element = LinearElementEditor.getElement(elementId, elementsMap);
|
const element = LinearElementEditor.getElement(elementId, elementsMap);
|
||||||
|
let customLineAngle = linearElementEditor.customLineAngle;
|
||||||
if (!element) {
|
if (!element) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -293,6 +296,12 @@ export class LinearElementEditor {
|
|||||||
const selectedIndex = selectedPointsIndices[0];
|
const selectedIndex = selectedPointsIndices[0];
|
||||||
const referencePoint =
|
const referencePoint =
|
||||||
element.points[selectedIndex === 0 ? 1 : selectedIndex - 1];
|
element.points[selectedIndex === 0 ? 1 : selectedIndex - 1];
|
||||||
|
customLineAngle =
|
||||||
|
linearElementEditor.customLineAngle ??
|
||||||
|
Math.atan(
|
||||||
|
(element.points[selectedIndex][1] - referencePoint[1]) /
|
||||||
|
(element.points[selectedIndex][0] - referencePoint[0]),
|
||||||
|
);
|
||||||
|
|
||||||
const [width, height] = LinearElementEditor._getShiftLockedDelta(
|
const [width, height] = LinearElementEditor._getShiftLockedDelta(
|
||||||
element,
|
element,
|
||||||
@ -300,6 +309,7 @@ export class LinearElementEditor {
|
|||||||
referencePoint,
|
referencePoint,
|
||||||
pointFrom(scenePointerX, scenePointerY),
|
pointFrom(scenePointerX, scenePointerY),
|
||||||
event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(),
|
event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(),
|
||||||
|
customLineAngle,
|
||||||
);
|
);
|
||||||
|
|
||||||
LinearElementEditor.movePoints(
|
LinearElementEditor.movePoints(
|
||||||
@ -421,6 +431,7 @@ export class LinearElementEditor {
|
|||||||
? lastClickedPoint
|
? lastClickedPoint
|
||||||
: -1,
|
: -1,
|
||||||
isDragging: true,
|
isDragging: true,
|
||||||
|
customLineAngle,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -524,6 +535,7 @@ export class LinearElementEditor {
|
|||||||
: selectedPointsIndices,
|
: selectedPointsIndices,
|
||||||
isDragging: false,
|
isDragging: false,
|
||||||
pointerOffset: { x: 0, y: 0 },
|
pointerOffset: { x: 0, y: 0 },
|
||||||
|
customLineAngle: null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1531,6 +1543,7 @@ export class LinearElementEditor {
|
|||||||
referencePoint: LocalPoint,
|
referencePoint: LocalPoint,
|
||||||
scenePointer: GlobalPoint,
|
scenePointer: GlobalPoint,
|
||||||
gridSize: NullableGridSize,
|
gridSize: NullableGridSize,
|
||||||
|
customLineAngle?: number,
|
||||||
) {
|
) {
|
||||||
const referencePointCoords = LinearElementEditor.getPointGlobalCoordinates(
|
const referencePointCoords = LinearElementEditor.getPointGlobalCoordinates(
|
||||||
element,
|
element,
|
||||||
@ -1556,6 +1569,7 @@ export class LinearElementEditor {
|
|||||||
referencePointCoords[1],
|
referencePointCoords[1],
|
||||||
gridX,
|
gridX,
|
||||||
gridY,
|
gridY,
|
||||||
|
customLineAngle,
|
||||||
);
|
);
|
||||||
|
|
||||||
return pointRotateRads(
|
return pointRotateRads(
|
||||||
|
@ -2,6 +2,12 @@ import {
|
|||||||
SHIFT_LOCKING_ANGLE,
|
SHIFT_LOCKING_ANGLE,
|
||||||
viewportCoordsToSceneCoords,
|
viewportCoordsToSceneCoords,
|
||||||
} from "@excalidraw/common";
|
} from "@excalidraw/common";
|
||||||
|
import {
|
||||||
|
normalizeRadians,
|
||||||
|
radiansBetweenAngles,
|
||||||
|
radiansDifference,
|
||||||
|
type Radians,
|
||||||
|
} from "@excalidraw/math";
|
||||||
|
|
||||||
import type { AppState, Offsets, Zoom } from "@excalidraw/excalidraw/types";
|
import type { AppState, Offsets, Zoom } from "@excalidraw/excalidraw/types";
|
||||||
|
|
||||||
@ -134,13 +140,42 @@ export const getLockedLinearCursorAlignSize = (
|
|||||||
originY: number,
|
originY: number,
|
||||||
x: number,
|
x: number,
|
||||||
y: number,
|
y: number,
|
||||||
|
customAngle?: number,
|
||||||
) => {
|
) => {
|
||||||
let width = x - originX;
|
let width = x - originX;
|
||||||
let height = y - originY;
|
let height = y - originY;
|
||||||
|
|
||||||
const lockedAngle =
|
const angle = Math.atan(height / width) as Radians;
|
||||||
Math.round(Math.atan(height / width) / SHIFT_LOCKING_ANGLE) *
|
let lockedAngle = (Math.round(angle / SHIFT_LOCKING_ANGLE) *
|
||||||
SHIFT_LOCKING_ANGLE;
|
SHIFT_LOCKING_ANGLE) as Radians;
|
||||||
|
|
||||||
|
if (customAngle) {
|
||||||
|
// If custom angle is provided, we check if the angle is close to the
|
||||||
|
// custom angle, snap to that if close engough, otherwise snap to the
|
||||||
|
// higher or lower angle depending on the current angle vs custom angle.
|
||||||
|
const lower = (Math.floor(customAngle / SHIFT_LOCKING_ANGLE) *
|
||||||
|
SHIFT_LOCKING_ANGLE) as Radians;
|
||||||
|
if (
|
||||||
|
radiansBetweenAngles(
|
||||||
|
angle,
|
||||||
|
lower,
|
||||||
|
(lower + SHIFT_LOCKING_ANGLE) as Radians,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
radiansDifference(angle, customAngle as Radians) <
|
||||||
|
SHIFT_LOCKING_ANGLE / 6
|
||||||
|
) {
|
||||||
|
lockedAngle = customAngle as Radians;
|
||||||
|
} else if (
|
||||||
|
normalizeRadians(angle) > normalizeRadians(customAngle as Radians)
|
||||||
|
) {
|
||||||
|
lockedAngle = (lower + SHIFT_LOCKING_ANGLE) as Radians;
|
||||||
|
} else {
|
||||||
|
lockedAngle = lower;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (lockedAngle === 0) {
|
if (lockedAngle === 0) {
|
||||||
height = 0;
|
height = 0;
|
||||||
|
@ -8628,6 +8628,7 @@ exports[`regression tests > key 5 selects arrow tool > [end of test] appState 1`
|
|||||||
"selectedElementsAreBeingDragged": false,
|
"selectedElementsAreBeingDragged": false,
|
||||||
"selectedGroupIds": {},
|
"selectedGroupIds": {},
|
||||||
"selectedLinearElement": LinearElementEditor {
|
"selectedLinearElement": LinearElementEditor {
|
||||||
|
"customLineAngle": null,
|
||||||
"elbowed": false,
|
"elbowed": false,
|
||||||
"elementId": "id0",
|
"elementId": "id0",
|
||||||
"endBindingElement": "keep",
|
"endBindingElement": "keep",
|
||||||
@ -8851,6 +8852,7 @@ exports[`regression tests > key 6 selects line tool > [end of test] appState 1`]
|
|||||||
"selectedElementsAreBeingDragged": false,
|
"selectedElementsAreBeingDragged": false,
|
||||||
"selectedGroupIds": {},
|
"selectedGroupIds": {},
|
||||||
"selectedLinearElement": LinearElementEditor {
|
"selectedLinearElement": LinearElementEditor {
|
||||||
|
"customLineAngle": null,
|
||||||
"elbowed": false,
|
"elbowed": false,
|
||||||
"elementId": "id0",
|
"elementId": "id0",
|
||||||
"endBindingElement": "keep",
|
"endBindingElement": "keep",
|
||||||
@ -9267,6 +9269,7 @@ exports[`regression tests > key a selects arrow tool > [end of test] appState 1`
|
|||||||
"selectedElementsAreBeingDragged": false,
|
"selectedElementsAreBeingDragged": false,
|
||||||
"selectedGroupIds": {},
|
"selectedGroupIds": {},
|
||||||
"selectedLinearElement": LinearElementEditor {
|
"selectedLinearElement": LinearElementEditor {
|
||||||
|
"customLineAngle": null,
|
||||||
"elbowed": false,
|
"elbowed": false,
|
||||||
"elementId": "id0",
|
"elementId": "id0",
|
||||||
"endBindingElement": "keep",
|
"endBindingElement": "keep",
|
||||||
@ -9670,6 +9673,7 @@ exports[`regression tests > key l selects line tool > [end of test] appState 1`]
|
|||||||
"selectedElementsAreBeingDragged": false,
|
"selectedElementsAreBeingDragged": false,
|
||||||
"selectedGroupIds": {},
|
"selectedGroupIds": {},
|
||||||
"selectedLinearElement": LinearElementEditor {
|
"selectedLinearElement": LinearElementEditor {
|
||||||
|
"customLineAngle": null,
|
||||||
"elbowed": false,
|
"elbowed": false,
|
||||||
"elementId": "id0",
|
"elementId": "id0",
|
||||||
"endBindingElement": "keep",
|
"endBindingElement": "keep",
|
||||||
|
@ -49,3 +49,35 @@ export function radiansToDegrees(degrees: Radians): Degrees {
|
|||||||
export function isRightAngleRads(rads: Radians): boolean {
|
export function isRightAngleRads(rads: Radians): boolean {
|
||||||
return Math.abs(Math.sin(2 * rads)) < PRECISION;
|
return Math.abs(Math.sin(2 * rads)) < PRECISION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function radiansBetweenAngles(
|
||||||
|
a: Radians,
|
||||||
|
min: Radians,
|
||||||
|
max: Radians,
|
||||||
|
): boolean {
|
||||||
|
a = normalizeRadians(a);
|
||||||
|
min = normalizeRadians(min);
|
||||||
|
max = normalizeRadians(max);
|
||||||
|
|
||||||
|
if (min < max) {
|
||||||
|
return a >= min && a <= max;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The range wraps around the 0 angle
|
||||||
|
return a >= min || a <= max;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function radiansDifference(a: Radians, b: Radians): Radians {
|
||||||
|
a = normalizeRadians(a);
|
||||||
|
b = normalizeRadians(b);
|
||||||
|
|
||||||
|
let diff = a - b;
|
||||||
|
|
||||||
|
if (diff < -Math.PI) {
|
||||||
|
diff = (diff + 2 * Math.PI) as Radians;
|
||||||
|
} else if (diff > Math.PI) {
|
||||||
|
diff = (diff - 2 * Math.PI) as Radians;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.abs(diff) as Radians;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user