Compare commits

...

4 Commits

Author SHA1 Message Date
Aakansha Doshi
9c10fe60f1 fix hitbox 2023-02-16 13:29:54 +05:30
Aakansha Doshi
96b172ebfa support rotation 2023-02-15 17:36:46 +05:30
Aakansha Doshi
16db74cedd support ellipse 2023-02-15 15:20:12 +05:30
Aakansha Doshi
4d1b31a171 feat: bind text to container when clicked on filled shape or element stroke 2023-02-15 13:32:47 +05:30
2 changed files with 106 additions and 1 deletions

View File

@ -226,6 +226,7 @@ import {
setEraserCursor, setEraserCursor,
updateActiveTool, updateActiveTool,
getShortcutKey, getShortcutKey,
isTransparent,
} from "../utils"; } from "../utils";
import { import {
ContextMenu, ContextMenu,
@ -264,6 +265,7 @@ import {
getContainerCenter, getContainerCenter,
getContainerDims, getContainerDims,
getTextBindableContainerAtPosition, getTextBindableContainerAtPosition,
isHittingContainerStroke,
isValidTextContainer, isValidTextContainer,
} from "../element/textElement"; } from "../element/textElement";
import { isHittingElementNotConsideringBoundingBox } from "../element/collision"; import { isHittingElementNotConsideringBoundingBox } from "../element/collision";
@ -2762,7 +2764,19 @@ class App extends React.Component<AppProps, AppState> {
sceneY, sceneY,
); );
if (container) { if (container) {
if (isArrowElement(container) || hasBoundTextElement(container)) { if (
isArrowElement(container) ||
hasBoundTextElement(container) ||
!isTransparent(
(container as ExcalidrawTextContainer).backgroundColor,
) ||
isHittingContainerStroke(
sceneX,
sceneY,
container,
this.state.zoom.value,
)
) {
const midPoint = getContainerCenter(container, this.state); const midPoint = getContainerCenter(container, this.state);
sceneX = midPoint.x; sceneX = midPoint.x;

View File

@ -28,6 +28,7 @@ import {
resetOriginalContainerCache, resetOriginalContainerCache,
updateOriginalContainerCache, updateOriginalContainerCache,
} from "./textWysiwyg"; } from "./textWysiwyg";
import { rotatePoint } from "../math";
export const normalizeText = (text: string) => { export const normalizeText = (text: string) => {
return ( return (
@ -723,3 +724,93 @@ export const isValidTextContainer = (element: ExcalidrawElement) => {
isArrowElement(element) isArrowElement(element)
); );
}; };
export const isHittingContainerStroke = (
x: number,
y: number,
container: ExcalidrawTextContainer,
zoom: number,
) => {
const [x1, y1, x2, y2, cx, cy] = getElementAbsoluteCoords(container);
const topLeft = [x1, y1];
const topRight = [x2, y1];
const bottomLeft = [x1, y2];
const bottomRight = [x2, y2];
const [counterRotateX, counterRotateY] = rotatePoint(
[x, y],
[cx, cy],
-container.angle,
);
const strokeWidth = container.strokeWidth;
const threshold = 10 / zoom;
if (container.type === "ellipse") {
const h = (topLeft[0] + topRight[0]) / 2;
const k = (topLeft[1] + bottomLeft[1]) / 2;
let a = container.width / 2 + strokeWidth / 2 + threshold;
let b = container.height / 2 + strokeWidth / 2 + threshold;
const checkPointOnOuterEllipse =
Math.pow(counterRotateX - h, 2) / Math.pow(a, 2) +
Math.pow(counterRotateY - k, 2) / Math.pow(b, 2);
a = container.width / 2 - strokeWidth / 2 - threshold;
b = container.height / 2 - strokeWidth / 2 - threshold;
const checkPointOnInnerEllipse =
Math.pow(counterRotateX - h, 2) / Math.pow(a, 2) +
Math.pow(counterRotateY - k, 2) / Math.pow(b, 2);
// The expression evaluates to 1 means point is on ellipse,
// < 1 means inside ellipse and > 1 means outside ellipse
if (
checkPointOnInnerEllipse === 1 ||
checkPointOnOuterEllipse === 1 ||
(checkPointOnInnerEllipse > 1 && checkPointOnOuterEllipse < 1)
) {
return true;
}
return false;
}
// Left Stroke
if (
counterRotateX >= topLeft[0] - strokeWidth / 2 - threshold &&
counterRotateX <= topLeft[0] + strokeWidth / 2 + threshold &&
counterRotateY >= topLeft[1] - threshold &&
counterRotateY <= bottomRight[1] + threshold
) {
return true;
}
// Top stroke
if (
counterRotateX >= topLeft[0] - threshold &&
counterRotateX <= topRight[0] + threshold &&
counterRotateY >= topLeft[1] - threshold - strokeWidth / 2 &&
counterRotateY <= topLeft[1] + threshold + strokeWidth / 2
) {
return true;
}
// Right stroke
if (
counterRotateX >= topRight[0] - threshold - strokeWidth / 2 &&
counterRotateX <= topRight[0] + threshold + strokeWidth / 2 &&
counterRotateY >= topRight[1] - threshold &&
counterRotateY <= bottomRight[1] + threshold
) {
return true;
}
// Bottom Stroke
if (
counterRotateX >= bottomLeft[0] - threshold &&
counterRotateX <= bottomRight[0] + threshold &&
counterRotateY >= bottomLeft[1] - threshold - strokeWidth / 2 &&
counterRotateY <= bottomLeft[1] + threshold + strokeWidth / 2
) {
return true;
}
return false;
};