mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
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:
parent
73bf50e8a8
commit
47f87f4ecb
36 changed files with 779 additions and 270 deletions
|
@ -7,6 +7,7 @@ import {
|
|||
ExcalidrawTextElementWithContainer,
|
||||
ExcalidrawFrameLikeElement,
|
||||
NonDeletedSceneElementsMap,
|
||||
ElementsMap,
|
||||
} from "../element/types";
|
||||
import {
|
||||
isTextElement,
|
||||
|
@ -137,6 +138,7 @@ export interface ExcalidrawElementWithCanvas {
|
|||
|
||||
const cappedElementCanvasSize = (
|
||||
element: NonDeletedExcalidrawElement,
|
||||
elementsMap: ElementsMap,
|
||||
zoom: Zoom,
|
||||
): {
|
||||
width: number;
|
||||
|
@ -155,7 +157,7 @@ const cappedElementCanvasSize = (
|
|||
|
||||
const padding = getCanvasPadding(element);
|
||||
|
||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
|
||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);
|
||||
const elementWidth =
|
||||
isLinearElement(element) || isFreeDrawElement(element)
|
||||
? distance(x1, x2)
|
||||
|
@ -200,7 +202,11 @@ const generateElementCanvas = (
|
|||
const context = canvas.getContext("2d")!;
|
||||
const padding = getCanvasPadding(element);
|
||||
|
||||
const { width, height, scale } = cappedElementCanvasSize(element, zoom);
|
||||
const { width, height, scale } = cappedElementCanvasSize(
|
||||
element,
|
||||
elementsMap,
|
||||
zoom,
|
||||
);
|
||||
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
@ -209,7 +215,7 @@ const generateElementCanvas = (
|
|||
let canvasOffsetY = 0;
|
||||
|
||||
if (isLinearElement(element) || isFreeDrawElement(element)) {
|
||||
const [x1, y1] = getElementAbsoluteCoords(element);
|
||||
const [x1, y1] = getElementAbsoluteCoords(element, elementsMap);
|
||||
|
||||
canvasOffsetX =
|
||||
element.x > x1
|
||||
|
@ -468,7 +474,7 @@ const drawElementFromCanvas = (
|
|||
const element = elementWithCanvas.element;
|
||||
const padding = getCanvasPadding(element);
|
||||
const zoom = elementWithCanvas.scale;
|
||||
let [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
|
||||
let [x1, y1, x2, y2] = getElementAbsoluteCoords(element, allElementsMap);
|
||||
|
||||
// Free draw elements will otherwise "shuffle" as the min x and y change
|
||||
if (isFreeDrawElement(element)) {
|
||||
|
@ -513,8 +519,10 @@ const drawElementFromCanvas = (
|
|||
elementWithCanvas.canvas.height,
|
||||
);
|
||||
|
||||
const [, , , , boundTextCx, boundTextCy] =
|
||||
getElementAbsoluteCoords(boundTextElement);
|
||||
const [, , , , boundTextCx, boundTextCy] = getElementAbsoluteCoords(
|
||||
boundTextElement,
|
||||
allElementsMap,
|
||||
);
|
||||
|
||||
tempCanvasContext.rotate(-element.angle);
|
||||
|
||||
|
@ -694,7 +702,7 @@ export const renderElement = (
|
|||
ShapeCache.generateElementShape(element, null);
|
||||
|
||||
if (renderConfig.isExporting) {
|
||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
|
||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);
|
||||
const cx = (x1 + x2) / 2 + appState.scrollX;
|
||||
const cy = (y1 + y2) / 2 + appState.scrollY;
|
||||
const shiftX = (x2 - x1) / 2 - (element.x - x1);
|
||||
|
@ -737,7 +745,7 @@ export const renderElement = (
|
|||
// rely on existing shapes
|
||||
ShapeCache.generateElementShape(element, renderConfig);
|
||||
if (renderConfig.isExporting) {
|
||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
|
||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);
|
||||
const cx = (x1 + x2) / 2 + appState.scrollX;
|
||||
const cy = (y1 + y2) / 2 + appState.scrollY;
|
||||
let shiftX = (x2 - x1) / 2 - (element.x - x1);
|
||||
|
@ -749,6 +757,7 @@ export const renderElement = (
|
|||
LinearElementEditor.getBoundTextElementPosition(
|
||||
container,
|
||||
element as ExcalidrawTextElementWithContainer,
|
||||
elementsMap,
|
||||
);
|
||||
shiftX = (x2 - x1) / 2 - (boundTextCoords.x - x1);
|
||||
shiftY = (y2 - y1) / 2 - (boundTextCoords.y - y1);
|
||||
|
@ -804,8 +813,10 @@ export const renderElement = (
|
|||
tempCanvasContext.rotate(-element.angle);
|
||||
|
||||
// Shift the canvas to center of bound text
|
||||
const [, , , , boundTextCx, boundTextCy] =
|
||||
getElementAbsoluteCoords(boundTextElement);
|
||||
const [, , , , boundTextCx, boundTextCy] = getElementAbsoluteCoords(
|
||||
boundTextElement,
|
||||
elementsMap,
|
||||
);
|
||||
const boundTextShiftX = (x1 + x2) / 2 - boundTextCx;
|
||||
const boundTextShiftY = (y1 + y2) / 2 - boundTextCy;
|
||||
tempCanvasContext.translate(-boundTextShiftX, -boundTextShiftY);
|
||||
|
@ -939,17 +950,18 @@ export const renderElementToSvg = (
|
|||
renderConfig: SVGRenderConfig,
|
||||
) => {
|
||||
const offset = { x: offsetX, y: offsetY };
|
||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
|
||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);
|
||||
let cx = (x2 - x1) / 2 - (element.x - x1);
|
||||
let cy = (y2 - y1) / 2 - (element.y - y1);
|
||||
if (isTextElement(element)) {
|
||||
const container = getContainerElement(element, elementsMap);
|
||||
if (isArrowElement(container)) {
|
||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(container);
|
||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(container, elementsMap);
|
||||
|
||||
const boundTextCoords = LinearElementEditor.getBoundTextElementPosition(
|
||||
container,
|
||||
element as ExcalidrawTextElementWithContainer,
|
||||
elementsMap,
|
||||
);
|
||||
cx = (x2 - x1) / 2 - (boundTextCoords.x - x1);
|
||||
cy = (y2 - y1) / 2 - (boundTextCoords.y - y1);
|
||||
|
@ -1151,6 +1163,7 @@ export const renderElementToSvg = (
|
|||
const boundTextCoords = LinearElementEditor.getBoundTextElementPosition(
|
||||
element,
|
||||
boundText,
|
||||
elementsMap,
|
||||
);
|
||||
|
||||
const maskX = offsetX + boundTextCoords.x - element.x;
|
||||
|
|
|
@ -17,6 +17,7 @@ import {
|
|||
GroupId,
|
||||
ExcalidrawBindableElement,
|
||||
ExcalidrawFrameLikeElement,
|
||||
ElementsMap,
|
||||
} from "../element/types";
|
||||
import {
|
||||
getElementAbsoluteCoords,
|
||||
|
@ -256,7 +257,10 @@ const renderLinearPointHandles = (
|
|||
context.save();
|
||||
context.translate(appState.scrollX, appState.scrollY);
|
||||
context.lineWidth = 1 / appState.zoom.value;
|
||||
const points = LinearElementEditor.getPointsGlobalCoordinates(element);
|
||||
const points = LinearElementEditor.getPointsGlobalCoordinates(
|
||||
element,
|
||||
elementsMap,
|
||||
);
|
||||
|
||||
const { POINT_HANDLE_SIZE } = LinearElementEditor;
|
||||
const radius = appState.editingLinearElement
|
||||
|
@ -340,6 +344,7 @@ const highlightPoint = (
|
|||
const renderLinearElementPointHighlight = (
|
||||
context: CanvasRenderingContext2D,
|
||||
appState: InteractiveCanvasAppState,
|
||||
elementsMap: ElementsMap,
|
||||
) => {
|
||||
const { elementId, hoverPointIndex } = appState.selectedLinearElement!;
|
||||
if (
|
||||
|
@ -356,6 +361,7 @@ const renderLinearElementPointHighlight = (
|
|||
const point = LinearElementEditor.getPointAtIndexGlobalCoordinates(
|
||||
element,
|
||||
hoverPointIndex,
|
||||
elementsMap,
|
||||
);
|
||||
context.save();
|
||||
context.translate(appState.scrollX, appState.scrollY);
|
||||
|
@ -510,12 +516,22 @@ const _renderInteractiveScene = ({
|
|||
appState.suggestedBindings
|
||||
.filter((binding) => binding != null)
|
||||
.forEach((suggestedBinding) => {
|
||||
renderBindingHighlight(context, appState, suggestedBinding!);
|
||||
renderBindingHighlight(
|
||||
context,
|
||||
appState,
|
||||
suggestedBinding!,
|
||||
elementsMap,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
if (appState.frameToHighlight) {
|
||||
renderFrameHighlight(context, appState, appState.frameToHighlight);
|
||||
renderFrameHighlight(
|
||||
context,
|
||||
appState,
|
||||
appState.frameToHighlight,
|
||||
elementsMap,
|
||||
);
|
||||
}
|
||||
|
||||
if (appState.elementsToHighlight) {
|
||||
|
@ -545,7 +561,7 @@ const _renderInteractiveScene = ({
|
|||
appState.selectedLinearElement &&
|
||||
appState.selectedLinearElement.hoverPointIndex >= 0
|
||||
) {
|
||||
renderLinearElementPointHighlight(context, appState);
|
||||
renderLinearElementPointHighlight(context, appState, elementsMap);
|
||||
}
|
||||
// Paint selected elements
|
||||
if (!appState.multiElement && !appState.editingLinearElement) {
|
||||
|
@ -608,7 +624,7 @@ const _renderInteractiveScene = ({
|
|||
|
||||
if (selectionColors.length) {
|
||||
const [elementX1, elementY1, elementX2, elementY2, cx, cy] =
|
||||
getElementAbsoluteCoords(element, true);
|
||||
getElementAbsoluteCoords(element, elementsMap, true);
|
||||
selections.push({
|
||||
angle: element.angle,
|
||||
elementX1,
|
||||
|
@ -666,7 +682,8 @@ const _renderInteractiveScene = ({
|
|||
const transformHandles = getTransformHandles(
|
||||
selectedElements[0],
|
||||
appState.zoom,
|
||||
"mouse", // when we render we don't know which pointer type so use mouse
|
||||
elementsMap,
|
||||
"mouse", // when we render we don't know which pointer type so use mouse,
|
||||
);
|
||||
if (!appState.viewModeEnabled && showBoundingBox) {
|
||||
renderTransformHandles(
|
||||
|
@ -953,7 +970,11 @@ const _renderStaticScene = ({
|
|||
element.groupIds.length > 0 &&
|
||||
appState.frameToHighlight &&
|
||||
appState.selectedElementIds[element.id] &&
|
||||
(elementOverlapsWithFrame(element, appState.frameToHighlight) ||
|
||||
(elementOverlapsWithFrame(
|
||||
element,
|
||||
appState.frameToHighlight,
|
||||
elementsMap,
|
||||
) ||
|
||||
element.groupIds.find((groupId) => groupsToBeAddedToFrame.has(groupId)))
|
||||
) {
|
||||
element.groupIds.forEach((groupId) =>
|
||||
|
@ -1004,7 +1025,7 @@ const _renderStaticScene = ({
|
|||
);
|
||||
}
|
||||
if (!isExporting) {
|
||||
renderLinkIcon(element, context, appState);
|
||||
renderLinkIcon(element, context, appState, elementsMap);
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error(error);
|
||||
|
@ -1048,7 +1069,7 @@ const _renderStaticScene = ({
|
|||
);
|
||||
}
|
||||
if (!isExporting) {
|
||||
renderLinkIcon(element, context, appState);
|
||||
renderLinkIcon(element, context, appState, elementsMap);
|
||||
}
|
||||
};
|
||||
// - when exporting the whole canvas, we DO NOT apply clipping
|
||||
|
@ -1247,6 +1268,7 @@ const renderBindingHighlight = (
|
|||
context: CanvasRenderingContext2D,
|
||||
appState: InteractiveCanvasAppState,
|
||||
suggestedBinding: SuggestedBinding,
|
||||
elementsMap: ElementsMap,
|
||||
) => {
|
||||
const renderHighlight = Array.isArray(suggestedBinding)
|
||||
? renderBindingHighlightForSuggestedPointBinding
|
||||
|
@ -1254,7 +1276,7 @@ const renderBindingHighlight = (
|
|||
|
||||
context.save();
|
||||
context.translate(appState.scrollX, appState.scrollY);
|
||||
renderHighlight(context, suggestedBinding as any);
|
||||
renderHighlight(context, suggestedBinding as any, elementsMap);
|
||||
|
||||
context.restore();
|
||||
};
|
||||
|
@ -1262,8 +1284,9 @@ const renderBindingHighlight = (
|
|||
const renderBindingHighlightForBindableElement = (
|
||||
context: CanvasRenderingContext2D,
|
||||
element: ExcalidrawBindableElement,
|
||||
elementsMap: ElementsMap,
|
||||
) => {
|
||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
|
||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);
|
||||
const width = x2 - x1;
|
||||
const height = y2 - y1;
|
||||
const threshold = maxBindingGap(element, width, height);
|
||||
|
@ -1323,8 +1346,9 @@ const renderFrameHighlight = (
|
|||
context: CanvasRenderingContext2D,
|
||||
appState: InteractiveCanvasAppState,
|
||||
frame: NonDeleted<ExcalidrawFrameLikeElement>,
|
||||
elementsMap: ElementsMap,
|
||||
) => {
|
||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(frame);
|
||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(frame, elementsMap);
|
||||
const width = x2 - x1;
|
||||
const height = y2 - y1;
|
||||
|
||||
|
@ -1398,6 +1422,7 @@ const renderElementsBoxHighlight = (
|
|||
const renderBindingHighlightForSuggestedPointBinding = (
|
||||
context: CanvasRenderingContext2D,
|
||||
suggestedBinding: SuggestedPointBinding,
|
||||
elementsMap: ElementsMap,
|
||||
) => {
|
||||
const [element, startOrEnd, bindableElement] = suggestedBinding;
|
||||
|
||||
|
@ -1416,6 +1441,7 @@ const renderBindingHighlightForSuggestedPointBinding = (
|
|||
const [x, y] = LinearElementEditor.getPointAtIndexGlobalCoordinates(
|
||||
element,
|
||||
index,
|
||||
elementsMap,
|
||||
);
|
||||
fillCircle(context, x, y, threshold);
|
||||
});
|
||||
|
@ -1426,9 +1452,10 @@ const renderLinkIcon = (
|
|||
element: NonDeletedExcalidrawElement,
|
||||
context: CanvasRenderingContext2D,
|
||||
appState: StaticCanvasAppState,
|
||||
elementsMap: ElementsMap,
|
||||
) => {
|
||||
if (element.link && !appState.selectedElementIds[element.id]) {
|
||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
|
||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap);
|
||||
const [x, y, width, height] = getLinkHandleFromCoords(
|
||||
[x1, y1, x2, y2],
|
||||
element.angle,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue