mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
fix: linear elements not selected on pointer up from hitting its bound text (#8285)
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
This commit is contained in:
parent
2427e622b0
commit
7b36de0476
4 changed files with 42 additions and 38 deletions
|
@ -224,8 +224,7 @@ import type {
|
||||||
ScrollBars,
|
ScrollBars,
|
||||||
} from "../scene/types";
|
} from "../scene/types";
|
||||||
import { getStateForZoom } from "../scene/zoom";
|
import { getStateForZoom } from "../scene/zoom";
|
||||||
import { findShapeByKey, getElementShape } from "../shapes";
|
import { findShapeByKey, getBoundTextShape, getElementShape } from "../shapes";
|
||||||
import type { GeometricShape } from "../../utils/geometry/shape";
|
|
||||||
import { getSelectionBoxShape } from "../../utils/geometry/shape";
|
import { getSelectionBoxShape } from "../../utils/geometry/shape";
|
||||||
import { isPointInShape } from "../../utils/collision";
|
import { isPointInShape } from "../../utils/collision";
|
||||||
import type {
|
import type {
|
||||||
|
@ -4515,37 +4514,6 @@ class App extends React.Component<AppProps, AppState> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getBoundTextShape(element: ExcalidrawElement): GeometricShape | null {
|
|
||||||
const boundTextElement = getBoundTextElement(
|
|
||||||
element,
|
|
||||||
this.scene.getNonDeletedElementsMap(),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (boundTextElement) {
|
|
||||||
if (element.type === "arrow") {
|
|
||||||
return getElementShape(
|
|
||||||
{
|
|
||||||
...boundTextElement,
|
|
||||||
// arrow's bound text accurate position is not stored in the element's property
|
|
||||||
// but rather calculated and returned from the following static method
|
|
||||||
...LinearElementEditor.getBoundTextElementPosition(
|
|
||||||
element,
|
|
||||||
boundTextElement,
|
|
||||||
this.scene.getNonDeletedElementsMap(),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
this.scene.getNonDeletedElementsMap(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return getElementShape(
|
|
||||||
boundTextElement,
|
|
||||||
this.scene.getNonDeletedElementsMap(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private getElementAtPosition(
|
private getElementAtPosition(
|
||||||
x: number,
|
x: number,
|
||||||
y: number,
|
y: number,
|
||||||
|
@ -4677,7 +4645,7 @@ class App extends React.Component<AppProps, AppState> {
|
||||||
const hitBoundTextOfElement = hitElementBoundText(
|
const hitBoundTextOfElement = hitElementBoundText(
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
this.getBoundTextShape(element),
|
getBoundTextShape(element, this.scene.getNonDeletedElementsMap()),
|
||||||
);
|
);
|
||||||
if (hitBoundTextOfElement) {
|
if (hitBoundTextOfElement) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -18,6 +18,7 @@ import {
|
||||||
isImageElement,
|
isImageElement,
|
||||||
isTextElement,
|
isTextElement,
|
||||||
} from "./typeChecks";
|
} from "./typeChecks";
|
||||||
|
import { getBoundTextShape } from "../shapes";
|
||||||
|
|
||||||
export const shouldTestInside = (element: ExcalidrawElement) => {
|
export const shouldTestInside = (element: ExcalidrawElement) => {
|
||||||
if (element.type === "arrow") {
|
if (element.type === "arrow") {
|
||||||
|
@ -97,6 +98,12 @@ export const hitElementBoundingBoxOnly = (
|
||||||
) => {
|
) => {
|
||||||
return (
|
return (
|
||||||
!hitElementItself(hitArgs) &&
|
!hitElementItself(hitArgs) &&
|
||||||
|
// bound text is considered part of the element (even if it's outside the bounding box)
|
||||||
|
!hitElementBoundText(
|
||||||
|
hitArgs.x,
|
||||||
|
hitArgs.y,
|
||||||
|
getBoundTextShape(hitArgs.element, elementsMap),
|
||||||
|
) &&
|
||||||
hitElementBoundingBox(hitArgs.x, hitArgs.y, hitArgs.element, elementsMap)
|
hitElementBoundingBox(hitArgs.x, hitArgs.y, hitArgs.element, elementsMap)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -105,6 +112,6 @@ export const hitElementBoundText = (
|
||||||
x: number,
|
x: number,
|
||||||
y: number,
|
y: number,
|
||||||
textShape: GeometricShape | null,
|
textShape: GeometricShape | null,
|
||||||
) => {
|
): boolean => {
|
||||||
return textShape && isPointInShape([x, y], textShape);
|
return !!textShape && isPointInShape([x, y], textShape);
|
||||||
};
|
};
|
||||||
|
|
|
@ -635,8 +635,7 @@ export const getMaxCharWidth = (font: FontString) => {
|
||||||
|
|
||||||
export const getBoundTextElementId = (container: ExcalidrawElement | null) => {
|
export const getBoundTextElementId = (container: ExcalidrawElement | null) => {
|
||||||
return container?.boundElements?.length
|
return container?.boundElements?.length
|
||||||
? container?.boundElements?.filter((ele) => ele.type === "text")[0]?.id ||
|
? container?.boundElements?.find((ele) => ele.type === "text")?.id || null
|
||||||
null
|
|
||||||
: null;
|
: null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@ import {
|
||||||
} from "./components/icons";
|
} from "./components/icons";
|
||||||
import { getElementAbsoluteCoords } from "./element";
|
import { getElementAbsoluteCoords } from "./element";
|
||||||
import { shouldTestInside } from "./element/collision";
|
import { shouldTestInside } from "./element/collision";
|
||||||
|
import { LinearElementEditor } from "./element/linearElementEditor";
|
||||||
|
import { getBoundTextElement } from "./element/textElement";
|
||||||
import type { ElementsMap, ExcalidrawElement } from "./element/types";
|
import type { ElementsMap, ExcalidrawElement } from "./element/types";
|
||||||
import { KEYS } from "./keys";
|
import { KEYS } from "./keys";
|
||||||
import { ShapeCache } from "./scene/ShapeCache";
|
import { ShapeCache } from "./scene/ShapeCache";
|
||||||
|
@ -159,3 +161,31 @@ export const getElementShape = (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getBoundTextShape = (
|
||||||
|
element: ExcalidrawElement,
|
||||||
|
elementsMap: ElementsMap,
|
||||||
|
): GeometricShape | null => {
|
||||||
|
const boundTextElement = getBoundTextElement(element, elementsMap);
|
||||||
|
|
||||||
|
if (boundTextElement) {
|
||||||
|
if (element.type === "arrow") {
|
||||||
|
return getElementShape(
|
||||||
|
{
|
||||||
|
...boundTextElement,
|
||||||
|
// arrow's bound text accurate position is not stored in the element's property
|
||||||
|
// but rather calculated and returned from the following static method
|
||||||
|
...LinearElementEditor.getBoundTextElementPosition(
|
||||||
|
element,
|
||||||
|
boundTextElement,
|
||||||
|
elementsMap,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
elementsMap,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return getElementShape(boundTextElement, elementsMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue