Removed unnessary context.restore() calls a using cached selectedElements in the interactive canvas
This commit is contained in:
parent
58dcafe8f6
commit
e58e9ec6d5
@ -1100,7 +1100,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const selectedElement = this.scene.getSelectedElements(this.state);
|
const selectedElements = this.scene.getSelectedElements(this.state);
|
||||||
const { renderTopRightUI, renderCustomStats } = this.props;
|
const { renderTopRightUI, renderCustomStats } = this.props;
|
||||||
|
|
||||||
const versionNonce = this.scene.getVersionNonce();
|
const versionNonce = this.scene.getVersionNonce();
|
||||||
@ -1180,12 +1180,12 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
<div className="excalidraw-textEditorContainer" />
|
<div className="excalidraw-textEditorContainer" />
|
||||||
<div className="excalidraw-contextMenuContainer" />
|
<div className="excalidraw-contextMenuContainer" />
|
||||||
<div className="excalidraw-eye-dropper-container" />
|
<div className="excalidraw-eye-dropper-container" />
|
||||||
{selectedElement.length === 1 &&
|
{selectedElements.length === 1 &&
|
||||||
!this.state.contextMenu &&
|
!this.state.contextMenu &&
|
||||||
this.state.showHyperlinkPopup && (
|
this.state.showHyperlinkPopup && (
|
||||||
<Hyperlink
|
<Hyperlink
|
||||||
key={selectedElement[0].id}
|
key={selectedElements[0].id}
|
||||||
element={selectedElement[0]}
|
element={selectedElements[0]}
|
||||||
setAppState={this.setAppState}
|
setAppState={this.setAppState}
|
||||||
onLinkOpen={this.props.onLinkOpen}
|
onLinkOpen={this.props.onLinkOpen}
|
||||||
setToast={this.setToast}
|
setToast={this.setToast}
|
||||||
@ -1229,6 +1229,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
canvas={this.interactiveCanvas}
|
canvas={this.interactiveCanvas}
|
||||||
elements={canvasElements}
|
elements={canvasElements}
|
||||||
visibleElements={visibleElements}
|
visibleElements={visibleElements}
|
||||||
|
selectedElements={selectedElements}
|
||||||
versionNonce={versionNonce}
|
versionNonce={versionNonce}
|
||||||
selectionNonce={
|
selectionNonce={
|
||||||
this.state.selectionElement?.versionNonce
|
this.state.selectionElement?.versionNonce
|
||||||
|
@ -19,6 +19,7 @@ type InteractiveCanvasProps = {
|
|||||||
canvas: HTMLCanvasElement | null;
|
canvas: HTMLCanvasElement | null;
|
||||||
elements: readonly NonDeletedExcalidrawElement[];
|
elements: readonly NonDeletedExcalidrawElement[];
|
||||||
visibleElements: readonly NonDeletedExcalidrawElement[];
|
visibleElements: readonly NonDeletedExcalidrawElement[];
|
||||||
|
selectedElements: readonly NonDeletedExcalidrawElement[];
|
||||||
versionNonce: number | undefined;
|
versionNonce: number | undefined;
|
||||||
selectionNonce: number | undefined;
|
selectionNonce: number | undefined;
|
||||||
scale: number;
|
scale: number;
|
||||||
@ -92,6 +93,7 @@ const InteractiveCanvas = (props: InteractiveCanvasProps) => {
|
|||||||
canvas: props.canvas,
|
canvas: props.canvas,
|
||||||
elements: props.elements,
|
elements: props.elements,
|
||||||
visibleElements: props.visibleElements,
|
visibleElements: props.visibleElements,
|
||||||
|
selectedElements: props.selectedElements,
|
||||||
scale: window.devicePixelRatio,
|
scale: window.devicePixelRatio,
|
||||||
appState: props.appState,
|
appState: props.appState,
|
||||||
renderConfig: {
|
renderConfig: {
|
||||||
@ -179,7 +181,8 @@ const areEqual = (
|
|||||||
// even if versionNonce didn't change (e.g. we filter elements out based
|
// even if versionNonce didn't change (e.g. we filter elements out based
|
||||||
// on appState)
|
// on appState)
|
||||||
prevProps.elements !== nextProps.elements ||
|
prevProps.elements !== nextProps.elements ||
|
||||||
prevProps.visibleElements !== nextProps.visibleElements
|
prevProps.visibleElements !== nextProps.visibleElements ||
|
||||||
|
prevProps.selectedElements !== nextProps.selectedElements
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -276,7 +276,7 @@ export const getTransformHandles = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const shouldShowBoundingBox = (
|
export const shouldShowBoundingBox = (
|
||||||
elements: NonDeletedExcalidrawElement[],
|
elements: readonly NonDeletedExcalidrawElement[],
|
||||||
appState: InteractiveCanvasAppState,
|
appState: InteractiveCanvasAppState,
|
||||||
) => {
|
) => {
|
||||||
if (appState.editingLinearElement) {
|
if (appState.editingLinearElement) {
|
||||||
|
@ -38,7 +38,6 @@ import {
|
|||||||
SCROLLBAR_COLOR,
|
SCROLLBAR_COLOR,
|
||||||
SCROLLBAR_WIDTH,
|
SCROLLBAR_WIDTH,
|
||||||
} from "../scene/scrollbars";
|
} from "../scene/scrollbars";
|
||||||
import { getSelectedElements } from "../scene/selection";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
renderElement,
|
renderElement,
|
||||||
@ -398,7 +397,6 @@ const getNormalizedCanvasDimensions = (
|
|||||||
const bootstrapCanvas = ({
|
const bootstrapCanvas = ({
|
||||||
canvas,
|
canvas,
|
||||||
scale,
|
scale,
|
||||||
zoom,
|
|
||||||
normalizedWidth,
|
normalizedWidth,
|
||||||
normalizedHeight,
|
normalizedHeight,
|
||||||
theme,
|
theme,
|
||||||
@ -407,7 +405,6 @@ const bootstrapCanvas = ({
|
|||||||
}: {
|
}: {
|
||||||
canvas: HTMLCanvasElement;
|
canvas: HTMLCanvasElement;
|
||||||
scale: number;
|
scale: number;
|
||||||
zoom: CommonCanvasAppState["zoom"];
|
|
||||||
normalizedWidth: number;
|
normalizedWidth: number;
|
||||||
normalizedHeight: number;
|
normalizedHeight: number;
|
||||||
theme?: CommonCanvasAppState["theme"];
|
theme?: CommonCanvasAppState["theme"];
|
||||||
@ -417,7 +414,6 @@ const bootstrapCanvas = ({
|
|||||||
const context = canvas.getContext("2d")!;
|
const context = canvas.getContext("2d")!;
|
||||||
|
|
||||||
context.setTransform(1, 0, 0, 1, 0, 0);
|
context.setTransform(1, 0, 0, 1, 0, 0);
|
||||||
context.save();
|
|
||||||
context.scale(scale, scale);
|
context.scale(scale, scale);
|
||||||
|
|
||||||
if (isExporting && theme === "dark") {
|
if (isExporting && theme === "dark") {
|
||||||
@ -442,10 +438,6 @@ const bootstrapCanvas = ({
|
|||||||
context.clearRect(0, 0, normalizedWidth, normalizedHeight);
|
context.clearRect(0, 0, normalizedWidth, normalizedHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply zoom
|
|
||||||
context.save();
|
|
||||||
context.scale(zoom.value, zoom.value);
|
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -453,6 +445,7 @@ const _renderInteractiveScene = ({
|
|||||||
canvas,
|
canvas,
|
||||||
elements,
|
elements,
|
||||||
visibleElements,
|
visibleElements,
|
||||||
|
selectedElements,
|
||||||
scale,
|
scale,
|
||||||
appState,
|
appState,
|
||||||
renderConfig,
|
renderConfig,
|
||||||
@ -471,9 +464,12 @@ const _renderInteractiveScene = ({
|
|||||||
scale,
|
scale,
|
||||||
normalizedWidth,
|
normalizedWidth,
|
||||||
normalizedHeight,
|
normalizedHeight,
|
||||||
zoom: appState.zoom,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Apply zoom
|
||||||
|
context.save();
|
||||||
|
context.scale(appState.zoom.value, appState.zoom.value);
|
||||||
|
|
||||||
let editingLinearElement: NonDeleted<ExcalidrawLinearElement> | undefined =
|
let editingLinearElement: NonDeleted<ExcalidrawLinearElement> | undefined =
|
||||||
undefined;
|
undefined;
|
||||||
|
|
||||||
@ -517,8 +513,7 @@ const _renderInteractiveScene = ({
|
|||||||
renderElementsBoxHighlight(context, appState, appState.elementsToHighlight);
|
renderElementsBoxHighlight(context, appState, appState.elementsToHighlight);
|
||||||
}
|
}
|
||||||
|
|
||||||
const locallySelectedElements = getSelectedElements(elements, appState);
|
const isFrameSelected = selectedElements.some((element) =>
|
||||||
const isFrameSelected = locallySelectedElements.some((element) =>
|
|
||||||
isFrameElement(element),
|
isFrameElement(element),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -526,13 +521,13 @@ const _renderInteractiveScene = ({
|
|||||||
// ShapeCache returns empty hence making sure that we get the
|
// ShapeCache returns empty hence making sure that we get the
|
||||||
// correct element from visible elements
|
// correct element from visible elements
|
||||||
if (
|
if (
|
||||||
locallySelectedElements.length === 1 &&
|
selectedElements.length === 1 &&
|
||||||
appState.editingLinearElement?.elementId === locallySelectedElements[0].id
|
appState.editingLinearElement?.elementId === selectedElements[0].id
|
||||||
) {
|
) {
|
||||||
renderLinearPointHandles(
|
renderLinearPointHandles(
|
||||||
context,
|
context,
|
||||||
appState,
|
appState,
|
||||||
locallySelectedElements[0] as NonDeleted<ExcalidrawLinearElement>,
|
selectedElements[0] as NonDeleted<ExcalidrawLinearElement>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -544,32 +539,27 @@ const _renderInteractiveScene = ({
|
|||||||
}
|
}
|
||||||
// Paint selected elements
|
// Paint selected elements
|
||||||
if (!appState.multiElement && !appState.editingLinearElement) {
|
if (!appState.multiElement && !appState.editingLinearElement) {
|
||||||
const showBoundingBox = shouldShowBoundingBox(
|
const showBoundingBox = shouldShowBoundingBox(selectedElements, appState);
|
||||||
locallySelectedElements,
|
|
||||||
appState,
|
|
||||||
);
|
|
||||||
|
|
||||||
const isSingleLinearElementSelected =
|
const isSingleLinearElementSelected =
|
||||||
locallySelectedElements.length === 1 &&
|
selectedElements.length === 1 && isLinearElement(selectedElements[0]);
|
||||||
isLinearElement(locallySelectedElements[0]);
|
|
||||||
// render selected linear element points
|
// render selected linear element points
|
||||||
if (
|
if (
|
||||||
isSingleLinearElementSelected &&
|
isSingleLinearElementSelected &&
|
||||||
appState.selectedLinearElement?.elementId ===
|
appState.selectedLinearElement?.elementId === selectedElements[0].id &&
|
||||||
locallySelectedElements[0].id &&
|
!selectedElements[0].locked
|
||||||
!locallySelectedElements[0].locked
|
|
||||||
) {
|
) {
|
||||||
renderLinearPointHandles(
|
renderLinearPointHandles(
|
||||||
context,
|
context,
|
||||||
appState,
|
appState,
|
||||||
locallySelectedElements[0] as ExcalidrawLinearElement,
|
selectedElements[0] as ExcalidrawLinearElement,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const selectionColor = renderConfig.selectionColor || oc.black;
|
const selectionColor = renderConfig.selectionColor || oc.black;
|
||||||
|
|
||||||
if (showBoundingBox) {
|
if (showBoundingBox) {
|
||||||
// Optimisation for finding quickly relevant element ids
|
// Optimisation for finding quickly relevant element ids
|
||||||
const locallySelectedIds = locallySelectedElements.reduce(
|
const locallySelectedIds = selectedElements.reduce(
|
||||||
(acc: Record<string, boolean>, element) => {
|
(acc: Record<string, boolean>, element) => {
|
||||||
acc[element.id] = true;
|
acc[element.id] = true;
|
||||||
return acc;
|
return acc;
|
||||||
@ -671,10 +661,10 @@ const _renderInteractiveScene = ({
|
|||||||
context.save();
|
context.save();
|
||||||
context.translate(appState.scrollX, appState.scrollY);
|
context.translate(appState.scrollX, appState.scrollY);
|
||||||
|
|
||||||
if (locallySelectedElements.length === 1) {
|
if (selectedElements.length === 1) {
|
||||||
context.fillStyle = oc.white;
|
context.fillStyle = oc.white;
|
||||||
const transformHandles = getTransformHandles(
|
const transformHandles = getTransformHandles(
|
||||||
locallySelectedElements[0],
|
selectedElements[0],
|
||||||
appState.zoom,
|
appState.zoom,
|
||||||
"mouse", // when we render we don't know which pointer type so use mouse
|
"mouse", // when we render we don't know which pointer type so use mouse
|
||||||
);
|
);
|
||||||
@ -684,13 +674,13 @@ const _renderInteractiveScene = ({
|
|||||||
renderConfig,
|
renderConfig,
|
||||||
appState,
|
appState,
|
||||||
transformHandles,
|
transformHandles,
|
||||||
locallySelectedElements[0].angle,
|
selectedElements[0].angle,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (locallySelectedElements.length > 1 && !appState.isRotating) {
|
} else if (selectedElements.length > 1 && !appState.isRotating) {
|
||||||
const dashedLinePadding = (DEFAULT_SPACING * 2) / appState.zoom.value;
|
const dashedLinePadding = (DEFAULT_SPACING * 2) / appState.zoom.value;
|
||||||
context.fillStyle = oc.white;
|
context.fillStyle = oc.white;
|
||||||
const [x1, y1, x2, y2] = getCommonBounds(locallySelectedElements);
|
const [x1, y1, x2, y2] = getCommonBounds(selectedElements);
|
||||||
const initialLineDash = context.getLineDash();
|
const initialLineDash = context.getLineDash();
|
||||||
context.setLineDash([2 / appState.zoom.value]);
|
context.setLineDash([2 / appState.zoom.value]);
|
||||||
const lineWidth = context.lineWidth;
|
const lineWidth = context.lineWidth;
|
||||||
@ -717,7 +707,7 @@ const _renderInteractiveScene = ({
|
|||||||
? OMIT_SIDES_FOR_FRAME
|
? OMIT_SIDES_FOR_FRAME
|
||||||
: OMIT_SIDES_FOR_MULTIPLE_ELEMENTS,
|
: OMIT_SIDES_FOR_MULTIPLE_ELEMENTS,
|
||||||
);
|
);
|
||||||
if (locallySelectedElements.some((element) => !element.locked)) {
|
if (selectedElements.some((element) => !element.locked)) {
|
||||||
renderTransformHandles(
|
renderTransformHandles(
|
||||||
context,
|
context,
|
||||||
renderConfig,
|
renderConfig,
|
||||||
@ -899,9 +889,6 @@ const _renderInteractiveScene = ({
|
|||||||
context.restore();
|
context.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
context.restore();
|
|
||||||
context.restore();
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
scrollBars,
|
scrollBars,
|
||||||
atLeastOneVisibleElement: visibleElements.length > 0,
|
atLeastOneVisibleElement: visibleElements.length > 0,
|
||||||
@ -934,12 +921,14 @@ const _renderStaticScene = ({
|
|||||||
scale,
|
scale,
|
||||||
normalizedWidth,
|
normalizedWidth,
|
||||||
normalizedHeight,
|
normalizedHeight,
|
||||||
zoom: appState.zoom,
|
|
||||||
theme: appState.theme,
|
theme: appState.theme,
|
||||||
isExporting,
|
isExporting,
|
||||||
viewBackgroundColor: appState.viewBackgroundColor,
|
viewBackgroundColor: appState.viewBackgroundColor,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Apply zoom
|
||||||
|
context.scale(appState.zoom.value, appState.zoom.value);
|
||||||
|
|
||||||
// Grid
|
// Grid
|
||||||
if (renderGrid && appState.gridSize) {
|
if (renderGrid && appState.gridSize) {
|
||||||
strokeGrid(
|
strokeGrid(
|
||||||
@ -1057,8 +1046,6 @@ const _renderStaticScene = ({
|
|||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
context.restore();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const renderInteractiveScene = <
|
export const renderInteractiveScene = <
|
||||||
|
@ -53,6 +53,7 @@ export type InteractiveSceneRenderConfig = {
|
|||||||
canvas: HTMLCanvasElement | null;
|
canvas: HTMLCanvasElement | null;
|
||||||
elements: readonly NonDeletedExcalidrawElement[];
|
elements: readonly NonDeletedExcalidrawElement[];
|
||||||
visibleElements: readonly NonDeletedExcalidrawElement[];
|
visibleElements: readonly NonDeletedExcalidrawElement[];
|
||||||
|
selectedElements: readonly NonDeletedExcalidrawElement[];
|
||||||
scale: number;
|
scale: number;
|
||||||
appState: InteractiveCanvasAppState;
|
appState: InteractiveCanvasAppState;
|
||||||
renderConfig: InteractiveCanvasRenderConfig;
|
renderConfig: InteractiveCanvasRenderConfig;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user