fix: remove scene from getElementAbsoluteCoords and dependent functions and use elementsMap (#7663)

* fix: remove scene from getElementAbsoluteCoords and dependent functions and use elementsMap

* lint

* fix

* use non deleted elements where possible

* use non deleted elements map in actions

* pass elementsMap instead of array to elementOverlapsWithFrame

* lint

* fix

* pass elementsMap to getElementsCorners

* pass elementsMap to getEligibleElementsForBinding

* pass elementsMap in bindOrUnbindSelectedElements and unbindLinearElements

* pass elementsMap in elementsAreInFrameBounds,elementOverlapsWithFrame,isCursorInFrame,getElementsInResizingFrame

* pass elementsMap in getElementsWithinSelection, getElementsCompletelyInFrame, isElementContainingFrame, getElementsInNewFrame

* pass elementsMap to getElementWithTransformHandleType

* pass elementsMap to getVisibleGaps, getMaximumGroups,getReferenceSnapPoints,snapDraggedElements

* lint

* pass elementsMap to bindTextToShapeAfterDuplication,bindLinearElementToElement,getTextBindableContainerAtPosition

* revert changes for bindTextToShapeAfterDuplication
This commit is contained in:
Aakansha Doshi 2024-02-16 11:35:01 +05:30 committed by GitHub
parent 73bf50e8a8
commit 47f87f4ecb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
36 changed files with 779 additions and 270 deletions

View file

@ -65,10 +65,11 @@ export const bindElementsToFramesAfterDuplication = (
export function isElementIntersectingFrame(
element: ExcalidrawElement,
frame: ExcalidrawFrameLikeElement,
elementsMap: ElementsMap,
) {
const frameLineSegments = getElementLineSegments(frame);
const frameLineSegments = getElementLineSegments(frame, elementsMap);
const elementLineSegments = getElementLineSegments(element);
const elementLineSegments = getElementLineSegments(element, elementsMap);
const intersecting = frameLineSegments.some((frameLineSegment) =>
elementLineSegments.some((elementLineSegment) =>
@ -82,9 +83,10 @@ export function isElementIntersectingFrame(
export const getElementsCompletelyInFrame = (
elements: readonly ExcalidrawElement[],
frame: ExcalidrawFrameLikeElement,
elementsMap: ElementsMap,
) =>
omitGroupsContainingFrameLikes(
getElementsWithinSelection(elements, frame, false),
getElementsWithinSelection(elements, frame, elementsMap, false),
).filter(
(element) =>
(!isFrameLikeElement(element) && !element.frameId) ||
@ -95,8 +97,9 @@ export const isElementContainingFrame = (
elements: readonly ExcalidrawElement[],
element: ExcalidrawElement,
frame: ExcalidrawFrameLikeElement,
elementsMap: ElementsMap,
) => {
return getElementsWithinSelection(elements, element).some(
return getElementsWithinSelection(elements, element, elementsMap).some(
(e) => e.id === frame.id,
);
};
@ -104,13 +107,22 @@ export const isElementContainingFrame = (
export const getElementsIntersectingFrame = (
elements: readonly ExcalidrawElement[],
frame: ExcalidrawFrameLikeElement,
) => elements.filter((element) => isElementIntersectingFrame(element, frame));
) => {
const elementsMap = arrayToMap(elements);
return elements.filter((element) =>
isElementIntersectingFrame(element, frame, elementsMap),
);
};
export const elementsAreInFrameBounds = (
elements: readonly ExcalidrawElement[],
frame: ExcalidrawFrameLikeElement,
elementsMap: ElementsMap,
) => {
const [frameX1, frameY1, frameX2, frameY2] = getElementAbsoluteCoords(frame);
const [frameX1, frameY1, frameX2, frameY2] = getElementAbsoluteCoords(
frame,
elementsMap,
);
const [elementX1, elementY1, elementX2, elementY2] =
getCommonBounds(elements);
@ -126,11 +138,12 @@ export const elementsAreInFrameBounds = (
export const elementOverlapsWithFrame = (
element: ExcalidrawElement,
frame: ExcalidrawFrameLikeElement,
elementsMap: ElementsMap,
) => {
return (
elementsAreInFrameBounds([element], frame) ||
isElementIntersectingFrame(element, frame) ||
isElementContainingFrame([frame], element, frame)
elementsAreInFrameBounds([element], frame, elementsMap) ||
isElementIntersectingFrame(element, frame, elementsMap) ||
isElementContainingFrame([frame], element, frame, elementsMap)
);
};
@ -140,8 +153,9 @@ export const isCursorInFrame = (
y: number;
},
frame: NonDeleted<ExcalidrawFrameLikeElement>,
elementsMap: ElementsMap,
) => {
const [fx1, fy1, fx2, fy2] = getElementAbsoluteCoords(frame);
const [fx1, fy1, fx2, fy2] = getElementAbsoluteCoords(frame, elementsMap);
return isPointWithinBounds(
[fx1, fy1],
@ -155,6 +169,7 @@ export const groupsAreAtLeastIntersectingTheFrame = (
groupIds: readonly string[],
frame: ExcalidrawFrameLikeElement,
) => {
const elementsMap = arrayToMap(elements);
const elementsInGroup = groupIds.flatMap((groupId) =>
getElementsInGroup(elements, groupId),
);
@ -165,8 +180,8 @@ export const groupsAreAtLeastIntersectingTheFrame = (
return !!elementsInGroup.find(
(element) =>
elementsAreInFrameBounds([element], frame) ||
isElementIntersectingFrame(element, frame),
elementsAreInFrameBounds([element], frame, elementsMap) ||
isElementIntersectingFrame(element, frame, elementsMap),
);
};
@ -175,6 +190,7 @@ export const groupsAreCompletelyOutOfFrame = (
groupIds: readonly string[],
frame: ExcalidrawFrameLikeElement,
) => {
const elementsMap = arrayToMap(elements);
const elementsInGroup = groupIds.flatMap((groupId) =>
getElementsInGroup(elements, groupId),
);
@ -186,8 +202,8 @@ export const groupsAreCompletelyOutOfFrame = (
return (
elementsInGroup.find(
(element) =>
elementsAreInFrameBounds([element], frame) ||
isElementIntersectingFrame(element, frame),
elementsAreInFrameBounds([element], frame, elementsMap) ||
isElementIntersectingFrame(element, frame, elementsMap),
) === undefined
);
};
@ -258,14 +274,15 @@ export const getElementsInResizingFrame = (
allElements: ExcalidrawElementsIncludingDeleted,
frame: ExcalidrawFrameLikeElement,
appState: AppState,
elementsMap: ElementsMap,
): ExcalidrawElement[] => {
const prevElementsInFrame = getFrameChildren(allElements, frame.id);
const nextElementsInFrame = new Set<ExcalidrawElement>(prevElementsInFrame);
const elementsCompletelyInFrame = new Set([
...getElementsCompletelyInFrame(allElements, frame),
...getElementsCompletelyInFrame(allElements, frame, elementsMap),
...prevElementsInFrame.filter((element) =>
isElementContainingFrame(allElements, element, frame),
isElementContainingFrame(allElements, element, frame, elementsMap),
),
]);
@ -283,7 +300,7 @@ export const getElementsInResizingFrame = (
);
for (const element of elementsNotCompletelyInFrame) {
if (!isElementIntersectingFrame(element, frame)) {
if (!isElementIntersectingFrame(element, frame, elementsMap)) {
if (element.groupIds.length === 0) {
nextElementsInFrame.delete(element);
}
@ -334,7 +351,7 @@ export const getElementsInResizingFrame = (
if (isSelected) {
const elementsInGroup = getElementsInGroup(allElements, id);
if (elementsAreInFrameBounds(elementsInGroup, frame)) {
if (elementsAreInFrameBounds(elementsInGroup, frame, elementsMap)) {
for (const element of elementsInGroup) {
nextElementsInFrame.add(element);
}
@ -348,12 +365,13 @@ export const getElementsInResizingFrame = (
};
export const getElementsInNewFrame = (
allElements: ExcalidrawElementsIncludingDeleted,
elements: ExcalidrawElementsIncludingDeleted,
frame: ExcalidrawFrameLikeElement,
elementsMap: ElementsMap,
) => {
return omitGroupsContainingFrameLikes(
allElements,
getElementsCompletelyInFrame(allElements, frame),
elements,
getElementsCompletelyInFrame(elements, frame, elementsMap),
);
};
@ -388,7 +406,7 @@ export const filterElementsEligibleAsFrameChildren = (
frame: ExcalidrawFrameLikeElement,
) => {
const otherFrames = new Set<ExcalidrawFrameLikeElement["id"]>();
const elementsMap = arrayToMap(elements);
elements = omitGroupsContainingFrameLikes(elements);
for (const element of elements) {
@ -415,14 +433,18 @@ export const filterElementsEligibleAsFrameChildren = (
if (!processedGroups.has(shallowestGroupId)) {
processedGroups.add(shallowestGroupId);
const groupElements = getElementsInGroup(elements, shallowestGroupId);
if (groupElements.some((el) => elementOverlapsWithFrame(el, frame))) {
if (
groupElements.some((el) =>
elementOverlapsWithFrame(el, frame, elementsMap),
)
) {
for (const child of groupElements) {
eligibleElements.push(child);
}
}
}
} else {
const overlaps = elementOverlapsWithFrame(element, frame);
const overlaps = elementOverlapsWithFrame(element, frame, elementsMap);
if (overlaps) {
eligibleElements.push(element);
}
@ -682,12 +704,12 @@ export const getTargetFrame = (
// given an element, return if the element is in some frame
export const isElementInFrame = (
element: ExcalidrawElement,
allElements: ElementsMap,
allElementsMap: ElementsMap,
appState: StaticCanvasAppState,
) => {
const frame = getTargetFrame(element, allElements, appState);
const frame = getTargetFrame(element, allElementsMap, appState);
const _element = isTextElement(element)
? getContainerElement(element, allElements) || element
? getContainerElement(element, allElementsMap) || element
: element;
if (frame) {
@ -703,16 +725,18 @@ export const isElementInFrame = (
}
if (_element.groupIds.length === 0) {
return elementOverlapsWithFrame(_element, frame);
return elementOverlapsWithFrame(_element, frame, allElementsMap);
}
const allElementsInGroup = new Set(
_element.groupIds.flatMap((gid) => getElementsInGroup(allElements, gid)),
_element.groupIds.flatMap((gid) =>
getElementsInGroup(allElementsMap, gid),
),
);
if (appState.editingGroupId && appState.selectedElementsAreBeingDragged) {
const selectedElements = new Set(
getSelectedElements(allElements, appState),
getSelectedElements(allElementsMap, appState),
);
const editingGroupOverlapsFrame = appState.frameToHighlight !== null;
@ -733,7 +757,7 @@ export const isElementInFrame = (
}
for (const elementInGroup of allElementsInGroup) {
if (elementOverlapsWithFrame(elementInGroup, frame)) {
if (elementOverlapsWithFrame(elementInGroup, frame, allElementsMap)) {
return true;
}
}