Compare commits
4 Commits
master
...
dwelle/hit
Author | SHA1 | Date | |
---|---|---|---|
|
c1b903395a | ||
|
96b172ebfa | ||
|
16db74cedd | ||
|
4d1b31a171 |
@ -226,6 +226,7 @@ import {
|
||||
setEraserCursor,
|
||||
updateActiveTool,
|
||||
getShortcutKey,
|
||||
isTransparent,
|
||||
} from "../utils";
|
||||
import {
|
||||
ContextMenu,
|
||||
@ -264,6 +265,7 @@ import {
|
||||
getContainerCenter,
|
||||
getContainerDims,
|
||||
getTextBindableContainerAtPosition,
|
||||
isHittingContainerStroke,
|
||||
isValidTextContainer,
|
||||
} from "../element/textElement";
|
||||
import { isHittingElementNotConsideringBoundingBox } from "../element/collision";
|
||||
@ -2762,7 +2764,19 @@ class App extends React.Component<AppProps, AppState> {
|
||||
sceneY,
|
||||
);
|
||||
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);
|
||||
|
||||
sceneX = midPoint.x;
|
||||
|
@ -28,6 +28,7 @@ import {
|
||||
resetOriginalContainerCache,
|
||||
updateOriginalContainerCache,
|
||||
} from "./textWysiwyg";
|
||||
import { rotatePoint } from "../math";
|
||||
|
||||
export const normalizeText = (text: string) => {
|
||||
return (
|
||||
@ -723,3 +724,93 @@ export const isValidTextContainer = (element: ExcalidrawElement) => {
|
||||
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;
|
||||
if (container.type === "ellipse") {
|
||||
const threshold = 10 * zoom;
|
||||
const h = (topLeft[0] + topRight[0]) / 2;
|
||||
const k = (topLeft[1] + bottomLeft[1]) / 2;
|
||||
let a = container.width / 2 + threshold;
|
||||
let b = container.height / 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 - threshold;
|
||||
b = container.height / 2 - strokeWidth - 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;
|
||||
}
|
||||
const threshold = 10 / zoom;
|
||||
|
||||
// Left Stroke
|
||||
if (
|
||||
counterRotateX >= topLeft[0] - threshold &&
|
||||
counterRotateX <= topLeft[0] + strokeWidth + 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 &&
|
||||
counterRotateY <= topLeft[1] + threshold + strokeWidth
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Right stroke
|
||||
if (
|
||||
counterRotateX >= topRight[0] - threshold - strokeWidth &&
|
||||
counterRotateX <= topRight[0] + threshold &&
|
||||
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 &&
|
||||
counterRotateY <= bottomLeft[1] + threshold
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
@ -37,7 +37,10 @@ import {
|
||||
getSelectedGroupIds,
|
||||
getElementsInGroup,
|
||||
} from "../groups";
|
||||
import { maxBindingGap } from "../element/collision";
|
||||
import {
|
||||
isHittingElementNotConsideringBoundingBox,
|
||||
maxBindingGap,
|
||||
} from "../element/collision";
|
||||
import {
|
||||
SuggestedBinding,
|
||||
SuggestedPointBinding,
|
||||
@ -60,6 +63,8 @@ import {
|
||||
getLinkHandleFromCoords,
|
||||
} from "../element/Hyperlink";
|
||||
import { isLinearElement } from "../element/typeChecks";
|
||||
import { rotatePoint } from "../math";
|
||||
import { isHittingContainerStroke } from "../element/textElement";
|
||||
|
||||
const hasEmojiSupport = supportsEmoji();
|
||||
export const DEFAULT_SPACING = 2;
|
||||
@ -407,9 +412,44 @@ export const _renderScene = ({
|
||||
|
||||
let editingLinearElement: NonDeleted<ExcalidrawLinearElement> | undefined =
|
||||
undefined;
|
||||
let idx = -1;
|
||||
visibleElements.forEach((element) => {
|
||||
idx++;
|
||||
try {
|
||||
const useProdAlgo = idx % 2 === 0;
|
||||
context.fillStyle = useProdAlgo ? "lime" : "red";
|
||||
const padding = 40 / renderConfig.zoom.value;
|
||||
const bounds = getCommonBounds([element]);
|
||||
const box = [
|
||||
bounds[0] + renderConfig.scrollX,
|
||||
bounds[1] + renderConfig.scrollY,
|
||||
bounds[2] + renderConfig.scrollX,
|
||||
bounds[3] + renderConfig.scrollY,
|
||||
];
|
||||
for (let x = box[0] - padding; x < box[2] + padding; x++) {
|
||||
for (let y = box[1] - padding; y < box[3] + padding; y++) {
|
||||
const sceneX = x - renderConfig.scrollX;
|
||||
const sceneY = y - renderConfig.scrollY;
|
||||
if (
|
||||
useProdAlgo
|
||||
? isHittingElementNotConsideringBoundingBox(element, appState, [
|
||||
sceneX,
|
||||
sceneY,
|
||||
])
|
||||
: isHittingContainerStroke(
|
||||
sceneX,
|
||||
sceneY,
|
||||
// @ts-ignore
|
||||
element,
|
||||
renderConfig.zoom.value,
|
||||
)
|
||||
) {
|
||||
context.fillRect(x, y, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
renderElement(element, rc, context, renderConfig, appState);
|
||||
|
||||
// Getting the element using LinearElementEditor during collab mismatches version - being one head of visible elements due to
|
||||
// ShapeCache returns empty hence making sure that we get the
|
||||
// correct element from visible elements
|
||||
|
Loading…
x
Reference in New Issue
Block a user