89 lines
2.5 KiB
TypeScript
89 lines
2.5 KiB
TypeScript
import { DEFAULT_TRANSFORM_HANDLE_SPACING } from "@excalidraw/common";
|
|
import {
|
|
pointFrom,
|
|
pointRotateRads,
|
|
type GlobalPoint,
|
|
type Radians,
|
|
} from "@excalidraw/math";
|
|
|
|
import type { EditorInterface } from "@excalidraw/common";
|
|
|
|
import type { ExcalidrawTextElement } from "@excalidraw/element/types";
|
|
|
|
const TEXT_AUTO_RESIZE_HANDLE_GAP = 12;
|
|
const TEXT_AUTO_RESIZE_HANDLE_LENGTH = 16;
|
|
const TEXT_AUTO_RESIZE_HANDLE_HITBOX_WIDTH = 10;
|
|
const TEXT_AUTO_RESIZE_HANDLE_HITBOX_HEIGHT =
|
|
TEXT_AUTO_RESIZE_HANDLE_LENGTH + 2;
|
|
const MAX_HANDLE_HEIGHT_RATIO = 0.8;
|
|
|
|
export const getTextBoxPadding = (zoomValue: number) =>
|
|
(DEFAULT_TRANSFORM_HANDLE_SPACING * 2) / zoomValue;
|
|
|
|
export const getTextAutoResizeHandle = (
|
|
textElement: ExcalidrawTextElement,
|
|
zoomValue: number,
|
|
formFactor: EditorInterface["formFactor"],
|
|
) => {
|
|
if (
|
|
formFactor !== "desktop" ||
|
|
TEXT_AUTO_RESIZE_HANDLE_LENGTH >
|
|
textElement.height * zoomValue * MAX_HANDLE_HEIGHT_RATIO
|
|
) {
|
|
return null;
|
|
}
|
|
|
|
const padding = getTextBoxPadding(zoomValue);
|
|
const gap = TEXT_AUTO_RESIZE_HANDLE_GAP / zoomValue;
|
|
const length = TEXT_AUTO_RESIZE_HANDLE_LENGTH / zoomValue;
|
|
const center = pointFrom(
|
|
textElement.x + textElement.width / 2,
|
|
textElement.y + textElement.height / 2,
|
|
);
|
|
const handleCenter = pointRotateRads(
|
|
pointFrom(center[0] + textElement.width / 2 + padding + gap, center[1]),
|
|
center,
|
|
textElement.angle,
|
|
);
|
|
|
|
return {
|
|
center: handleCenter,
|
|
start: pointRotateRads(
|
|
pointFrom(handleCenter[0], handleCenter[1] - length / 2),
|
|
handleCenter,
|
|
textElement.angle,
|
|
) as GlobalPoint,
|
|
end: pointRotateRads(
|
|
pointFrom(handleCenter[0], handleCenter[1] + length / 2),
|
|
handleCenter,
|
|
textElement.angle,
|
|
) as GlobalPoint,
|
|
hitboxWidth: TEXT_AUTO_RESIZE_HANDLE_HITBOX_WIDTH / zoomValue,
|
|
hitboxHeight: TEXT_AUTO_RESIZE_HANDLE_HITBOX_HEIGHT / zoomValue,
|
|
};
|
|
};
|
|
|
|
export const isPointHittingTextAutoResizeHandle = (
|
|
point: Readonly<{ x: number; y: number }>,
|
|
textElement: ExcalidrawTextElement,
|
|
zoomValue: number,
|
|
formFactor: EditorInterface["formFactor"],
|
|
) => {
|
|
const handle = getTextAutoResizeHandle(textElement, zoomValue, formFactor);
|
|
|
|
if (!handle) {
|
|
return false;
|
|
}
|
|
|
|
const unrotatedPoint = pointRotateRads(
|
|
pointFrom(point.x, point.y),
|
|
handle.center,
|
|
-textElement.angle as Radians,
|
|
);
|
|
|
|
return (
|
|
Math.abs(unrotatedPoint[0] - handle.center[0]) <= handle.hitboxWidth / 2 &&
|
|
Math.abs(unrotatedPoint[1] - handle.center[1]) <= handle.hitboxHeight / 2
|
|
);
|
|
};
|