mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-04-14 16:40:58 -04:00
fix: collision regressions from vector geometry rewrite (#7902)
This commit is contained in:
parent
f92f04c13c
commit
bbcca06b94
2 changed files with 49 additions and 8 deletions
|
@ -230,6 +230,7 @@ import {
|
||||||
getEllipseShape,
|
getEllipseShape,
|
||||||
getFreedrawShape,
|
getFreedrawShape,
|
||||||
getPolygonShape,
|
getPolygonShape,
|
||||||
|
getSelectionBoxShape,
|
||||||
} from "../../utils/geometry/shape";
|
} from "../../utils/geometry/shape";
|
||||||
import { isPointInShape } from "../../utils/collision";
|
import { isPointInShape } from "../../utils/collision";
|
||||||
import {
|
import {
|
||||||
|
@ -416,7 +417,6 @@ import { withBatchedUpdates, withBatchedUpdatesThrottled } from "../reactUtils";
|
||||||
import { getRenderOpacity } from "../renderer/renderElement";
|
import { getRenderOpacity } from "../renderer/renderElement";
|
||||||
import {
|
import {
|
||||||
hitElementBoundText,
|
hitElementBoundText,
|
||||||
hitElementBoundingBox,
|
|
||||||
hitElementBoundingBoxOnly,
|
hitElementBoundingBoxOnly,
|
||||||
hitElementItself,
|
hitElementItself,
|
||||||
shouldTestInside,
|
shouldTestInside,
|
||||||
|
@ -4462,10 +4462,18 @@ class App extends React.Component<AppProps, AppState> {
|
||||||
|
|
||||||
// If we're hitting element with highest z-index only on its bounding box
|
// If we're hitting element with highest z-index only on its bounding box
|
||||||
// while also hitting other element figure, the latter should be considered.
|
// while also hitting other element figure, the latter should be considered.
|
||||||
return isPointInShape(
|
return hitElementItself({
|
||||||
[x, y],
|
x,
|
||||||
this.getElementShape(elementWithHighestZIndex),
|
y,
|
||||||
)
|
element: elementWithHighestZIndex,
|
||||||
|
shape: this.getElementShape(elementWithHighestZIndex),
|
||||||
|
// when overlapping, we would like to be more precise
|
||||||
|
// this also avoids the need to update past tests
|
||||||
|
threshold: this.getHitThreshold() / 2,
|
||||||
|
frameNameBound: isFrameLikeElement(elementWithHighestZIndex)
|
||||||
|
? this.frameNameBoundsCache.get(elementWithHighestZIndex)
|
||||||
|
: null,
|
||||||
|
})
|
||||||
? elementWithHighestZIndex
|
? elementWithHighestZIndex
|
||||||
: allHitElements[allHitElements.length - 2];
|
: allHitElements[allHitElements.length - 2];
|
||||||
}
|
}
|
||||||
|
@ -4540,13 +4548,13 @@ class App extends React.Component<AppProps, AppState> {
|
||||||
this.state.selectedElementIds[element.id] &&
|
this.state.selectedElementIds[element.id] &&
|
||||||
shouldShowBoundingBox([element], this.state)
|
shouldShowBoundingBox([element], this.state)
|
||||||
) {
|
) {
|
||||||
return hitElementBoundingBox(
|
const selectionShape = getSelectionBoxShape(
|
||||||
x,
|
|
||||||
y,
|
|
||||||
element,
|
element,
|
||||||
this.scene.getNonDeletedElementsMap(),
|
this.scene.getNonDeletedElementsMap(),
|
||||||
this.getHitThreshold(),
|
this.getHitThreshold(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return isPointInShape([x, y], selectionShape);
|
||||||
}
|
}
|
||||||
|
|
||||||
// take bound text element into consideration for hit collision as well
|
// take bound text element into consideration for hit collision as well
|
||||||
|
|
|
@ -12,8 +12,11 @@
|
||||||
* to pure shapes
|
* to pure shapes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { getElementAbsoluteCoords } from "../../excalidraw/element";
|
||||||
import {
|
import {
|
||||||
|
ElementsMap,
|
||||||
ExcalidrawDiamondElement,
|
ExcalidrawDiamondElement,
|
||||||
|
ExcalidrawElement,
|
||||||
ExcalidrawEllipseElement,
|
ExcalidrawEllipseElement,
|
||||||
ExcalidrawEmbeddableElement,
|
ExcalidrawEmbeddableElement,
|
||||||
ExcalidrawFrameLikeElement,
|
ExcalidrawFrameLikeElement,
|
||||||
|
@ -133,6 +136,36 @@ export const getPolygonShape = (
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// return the selection box for an element, possibly rotated as well
|
||||||
|
export const getSelectionBoxShape = (
|
||||||
|
element: ExcalidrawElement,
|
||||||
|
elementsMap: ElementsMap,
|
||||||
|
padding = 10,
|
||||||
|
) => {
|
||||||
|
let [x1, y1, x2, y2, cx, cy] = getElementAbsoluteCoords(
|
||||||
|
element,
|
||||||
|
elementsMap,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
|
||||||
|
x1 -= padding;
|
||||||
|
x2 += padding;
|
||||||
|
y1 -= padding;
|
||||||
|
y2 += padding;
|
||||||
|
|
||||||
|
const angleInDegrees = angleToDegrees(element.angle);
|
||||||
|
const center: Point = [cx, cy];
|
||||||
|
const topLeft = pointRotate([x1, y1], angleInDegrees, center);
|
||||||
|
const topRight = pointRotate([x2, y1], angleInDegrees, center);
|
||||||
|
const bottomLeft = pointRotate([x1, y2], angleInDegrees, center);
|
||||||
|
const bottomRight = pointRotate([x2, y2], angleInDegrees, center);
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: "polygon",
|
||||||
|
data: [topLeft, topRight, bottomRight, bottomLeft],
|
||||||
|
} as GeometricShape;
|
||||||
|
};
|
||||||
|
|
||||||
// ellipse
|
// ellipse
|
||||||
export const getEllipseShape = (
|
export const getEllipseShape = (
|
||||||
element: ExcalidrawEllipseElement,
|
element: ExcalidrawEllipseElement,
|
||||||
|
|
Loading…
Add table
Reference in a new issue