1
0
mirror of https://github.com/excalidraw/excalidraw.git synced 2024-11-10 11:35:52 +01:00

feat: support customizing what parts of frames are rendered (#6752)

This commit is contained in:
David Luzar 2023-07-10 17:13:44 +02:00 committed by GitHub
parent 49e4289878
commit cf0413338e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 472 additions and 88 deletions

@ -90,8 +90,8 @@ export const actionRemoveAllElementsFromFrame = register({
predicate: (elements, appState) => isSingleFrameSelected(elements, appState),
});
export const actionToggleFrameRendering = register({
name: "toggleFrameRendering",
export const actionupdateFrameRendering = register({
name: "updateFrameRendering",
viewMode: true,
trackEvent: { category: "canvas" },
perform: (elements, appState) => {
@ -99,13 +99,16 @@ export const actionToggleFrameRendering = register({
elements,
appState: {
...appState,
shouldRenderFrames: !appState.shouldRenderFrames,
frameRendering: {
...appState.frameRendering,
enabled: !appState.frameRendering.enabled,
},
},
commitToHistory: false,
};
},
contextItemLabel: "labels.toggleFrameRendering",
checked: (appState: AppState) => appState.shouldRenderFrames,
contextItemLabel: "labels.updateFrameRendering",
checked: (appState: AppState) => appState.frameRendering.enabled,
});
export const actionSetFrameAsActiveTool = register({

@ -119,7 +119,7 @@ export type ActionName =
| "toggleHandTool"
| "selectAllElementsInFrame"
| "removeAllElementsFromFrame"
| "toggleFrameRendering"
| "updateFrameRendering"
| "setFrameAsActiveTool"
| "createContainerFromText"
| "wrapTextInContainer";

@ -84,7 +84,7 @@ export const getDefaultAppState = (): Omit<
showStats: false,
startBoundElement: null,
suggestedBindings: [],
shouldRenderFrames: true,
frameRendering: { enabled: true, clip: true, name: true, outline: true },
frameToHighlight: null,
editingFrame: null,
elementsToHighlight: null,
@ -191,7 +191,7 @@ const APP_STATE_STORAGE_CONF = (<
showStats: { browser: true, export: false, server: false },
startBoundElement: { browser: false, export: false, server: false },
suggestedBindings: { browser: false, export: false, server: false },
shouldRenderFrames: { browser: false, export: false, server: false },
frameRendering: { browser: false, export: false, server: false },
frameToHighlight: { browser: false, export: false, server: false },
editingFrame: { browser: false, export: false, server: false },
elementsToHighlight: { browser: false, export: false, server: false },

@ -505,7 +505,7 @@ class App extends React.Component<AppProps, AppState> {
setActiveTool: this.setActiveTool,
setCursor: this.setCursor,
resetCursor: this.resetCursor,
toggleFrameRendering: this.toggleFrameRendering,
updateFrameRendering: this.updateFrameRendering,
toggleSidebar: this.toggleSidebar,
} as const;
if (typeof excalidrawRef === "function") {
@ -651,7 +651,7 @@ class App extends React.Component<AppProps, AppState> {
};
private renderFrameNames = () => {
if (!this.state.shouldRenderFrames) {
if (!this.state.frameRendering.enabled || !this.state.frameRendering.name) {
return null;
}
@ -2208,10 +2208,23 @@ class App extends React.Component<AppProps, AppState> {
});
};
toggleFrameRendering = () => {
updateFrameRendering = (
opts:
| Partial<AppState["frameRendering"]>
| ((
prevState: AppState["frameRendering"],
) => Partial<AppState["frameRendering"]>),
) => {
this.setState((prevState) => {
const next =
typeof opts === "function" ? opts(prevState.frameRendering) : opts;
return {
shouldRenderFrames: !prevState.shouldRenderFrames,
frameRendering: {
enabled: next?.enabled ?? prevState.frameRendering.enabled,
clip: next?.clip ?? prevState.frameRendering.clip,
name: next?.name ?? prevState.frameRendering.name,
outline: next?.outline ?? prevState.frameRendering.outline,
},
};
});
};
@ -3089,7 +3102,9 @@ class App extends React.Component<AppProps, AppState> {
).filter((element) => {
// hitting a frame's element from outside the frame is not considered a hit
const containingFrame = getContainingFrame(element);
return containingFrame && this.state.shouldRenderFrames
return containingFrame &&
this.state.frameRendering.enabled &&
this.state.frameRendering.clip
? isCursorInFrame({ x, y }, containingFrame)
: true;
});

@ -931,7 +931,11 @@ export const renderElement = (
break;
}
case "frame": {
if (!renderConfig.isExporting && appState.shouldRenderFrames) {
if (
!renderConfig.isExporting &&
appState.frameRendering.enabled &&
appState.frameRendering.outline
) {
context.save();
context.translate(
element.x + renderConfig.scrollX,

@ -470,7 +470,9 @@ export const _renderScene = ({
if (
frameId &&
((renderConfig.isExporting && isOnlyExportingSingleFrame(elements)) ||
(!renderConfig.isExporting && appState.shouldRenderFrames))
(!renderConfig.isExporting &&
appState.frameRendering.enabled &&
appState.frameRendering.clip))
) {
context.save();

@ -314,6 +314,12 @@ Object {
"exportScale": 1,
"exportWithDarkMode": false,
"fileHandle": null,
"frameRendering": Object {
"clip": true,
"enabled": true,
"name": true,
"outline": true,
},
"frameToHighlight": null,
"gridSize": null,
"height": 100,
@ -353,7 +359,6 @@ Object {
"selectedLinearElement": null,
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"shouldRenderFrames": true,
"showHyperlinkPopup": false,
"showStats": false,
"showWelcomeScreen": true,
@ -501,6 +506,12 @@ Object {
"exportScale": 1,
"exportWithDarkMode": false,
"fileHandle": null,
"frameRendering": Object {
"clip": true,
"enabled": true,
"name": true,
"outline": true,
},
"frameToHighlight": null,
"gridSize": null,
"height": 100,
@ -537,7 +548,6 @@ Object {
"selectedLinearElement": null,
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"shouldRenderFrames": true,
"showHyperlinkPopup": false,
"showStats": false,
"showWelcomeScreen": true,
@ -694,6 +704,12 @@ Object {
"exportScale": 1,
"exportWithDarkMode": false,
"fileHandle": null,
"frameRendering": Object {
"clip": true,
"enabled": true,
"name": true,
"outline": true,
},
"frameToHighlight": null,
"gridSize": null,
"height": 100,
@ -730,7 +746,6 @@ Object {
"selectedLinearElement": null,
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"shouldRenderFrames": true,
"showHyperlinkPopup": false,
"showStats": false,
"showWelcomeScreen": true,
@ -1061,6 +1076,12 @@ Object {
"exportScale": 1,
"exportWithDarkMode": false,
"fileHandle": null,
"frameRendering": Object {
"clip": true,
"enabled": true,
"name": true,
"outline": true,
},
"frameToHighlight": null,
"gridSize": null,
"height": 100,
@ -1097,7 +1118,6 @@ Object {
"selectedLinearElement": null,
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"shouldRenderFrames": true,
"showHyperlinkPopup": false,
"showStats": false,
"showWelcomeScreen": true,
@ -1428,6 +1448,12 @@ Object {
"exportScale": 1,
"exportWithDarkMode": false,
"fileHandle": null,
"frameRendering": Object {
"clip": true,
"enabled": true,
"name": true,
"outline": true,
},
"frameToHighlight": null,
"gridSize": null,
"height": 100,
@ -1464,7 +1490,6 @@ Object {
"selectedLinearElement": null,
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"shouldRenderFrames": true,
"showHyperlinkPopup": false,
"showStats": false,
"showWelcomeScreen": true,
@ -1621,6 +1646,12 @@ Object {
"exportScale": 1,
"exportWithDarkMode": false,
"fileHandle": null,
"frameRendering": Object {
"clip": true,
"enabled": true,
"name": true,
"outline": true,
},
"frameToHighlight": null,
"gridSize": null,
"height": 100,
@ -1655,7 +1686,6 @@ Object {
"selectedLinearElement": null,
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"shouldRenderFrames": true,
"showHyperlinkPopup": false,
"showStats": false,
"showWelcomeScreen": true,
@ -1851,6 +1881,12 @@ Object {
"exportScale": 1,
"exportWithDarkMode": false,
"fileHandle": null,
"frameRendering": Object {
"clip": true,
"enabled": true,
"name": true,
"outline": true,
},
"frameToHighlight": null,
"gridSize": null,
"height": 100,
@ -1887,7 +1923,6 @@ Object {
"selectedLinearElement": null,
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"shouldRenderFrames": true,
"showHyperlinkPopup": false,
"showStats": false,
"showWelcomeScreen": true,
@ -2146,6 +2181,12 @@ Object {
"exportScale": 1,
"exportWithDarkMode": false,
"fileHandle": null,
"frameRendering": Object {
"clip": true,
"enabled": true,
"name": true,
"outline": true,
},
"frameToHighlight": null,
"gridSize": null,
"height": 100,
@ -2187,7 +2228,6 @@ Object {
"selectedLinearElement": null,
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"shouldRenderFrames": true,
"showHyperlinkPopup": false,
"showStats": false,
"showWelcomeScreen": true,
@ -2529,6 +2569,12 @@ Object {
"exportScale": 1,
"exportWithDarkMode": false,
"fileHandle": null,
"frameRendering": Object {
"clip": true,
"enabled": true,
"name": true,
"outline": true,
},
"frameToHighlight": null,
"gridSize": null,
"height": 100,
@ -2565,7 +2611,6 @@ Object {
"selectedLinearElement": null,
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"shouldRenderFrames": true,
"showHyperlinkPopup": false,
"showStats": false,
"showWelcomeScreen": true,
@ -3402,6 +3447,12 @@ Object {
"exportScale": 1,
"exportWithDarkMode": false,
"fileHandle": null,
"frameRendering": Object {
"clip": true,
"enabled": true,
"name": true,
"outline": true,
},
"frameToHighlight": null,
"gridSize": null,
"height": 100,
@ -3438,7 +3489,6 @@ Object {
"selectedLinearElement": null,
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"shouldRenderFrames": true,
"showHyperlinkPopup": false,
"showStats": false,
"showWelcomeScreen": true,
@ -3769,6 +3819,12 @@ Object {
"exportScale": 1,
"exportWithDarkMode": false,
"fileHandle": null,
"frameRendering": Object {
"clip": true,
"enabled": true,
"name": true,
"outline": true,
},
"frameToHighlight": null,
"gridSize": null,
"height": 100,
@ -3805,7 +3861,6 @@ Object {
"selectedLinearElement": null,
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"shouldRenderFrames": true,
"showHyperlinkPopup": false,
"showStats": false,
"showWelcomeScreen": true,
@ -4136,6 +4191,12 @@ Object {
"exportScale": 1,
"exportWithDarkMode": false,
"fileHandle": null,
"frameRendering": Object {
"clip": true,
"enabled": true,
"name": true,
"outline": true,
},
"frameToHighlight": null,
"gridSize": null,
"height": 100,
@ -4175,7 +4236,6 @@ Object {
"selectedLinearElement": null,
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"shouldRenderFrames": true,
"showHyperlinkPopup": false,
"showStats": false,
"showWelcomeScreen": true,
@ -4862,6 +4922,12 @@ Object {
"exportScale": 1,
"exportWithDarkMode": false,
"fileHandle": null,
"frameRendering": Object {
"clip": true,
"enabled": true,
"name": true,
"outline": true,
},
"frameToHighlight": null,
"gridSize": null,
"height": 100,
@ -4901,7 +4967,6 @@ Object {
"selectedLinearElement": null,
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"shouldRenderFrames": true,
"showHyperlinkPopup": false,
"showStats": false,
"showWelcomeScreen": true,
@ -5436,6 +5501,12 @@ Object {
"exportScale": 1,
"exportWithDarkMode": false,
"fileHandle": null,
"frameRendering": Object {
"clip": true,
"enabled": true,
"name": true,
"outline": true,
},
"frameToHighlight": null,
"gridSize": null,
"height": 100,
@ -5477,7 +5548,6 @@ Object {
"selectedLinearElement": null,
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"shouldRenderFrames": true,
"showHyperlinkPopup": false,
"showStats": false,
"showWelcomeScreen": true,
@ -5934,6 +6004,12 @@ Object {
"exportScale": 1,
"exportWithDarkMode": false,
"fileHandle": null,
"frameRendering": Object {
"clip": true,
"enabled": true,
"name": true,
"outline": true,
},
"frameToHighlight": null,
"gridSize": null,
"height": 100,
@ -5968,7 +6044,6 @@ Object {
"selectedLinearElement": null,
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"shouldRenderFrames": true,
"showHyperlinkPopup": false,
"showStats": false,
"showWelcomeScreen": true,
@ -6324,6 +6399,12 @@ Object {
"exportScale": 1,
"exportWithDarkMode": false,
"fileHandle": null,
"frameRendering": Object {
"clip": true,
"enabled": true,
"name": true,
"outline": true,
},
"frameToHighlight": null,
"gridSize": null,
"height": 100,
@ -6360,7 +6441,6 @@ Object {
"selectedLinearElement": null,
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"shouldRenderFrames": true,
"showHyperlinkPopup": false,
"showStats": false,
"showWelcomeScreen": true,
@ -6692,6 +6772,12 @@ Object {
"exportScale": 1,
"exportWithDarkMode": false,
"fileHandle": null,
"frameRendering": Object {
"clip": true,
"enabled": true,
"name": true,
"outline": true,
},
"frameToHighlight": null,
"gridSize": null,
"height": 100,
@ -6728,7 +6814,6 @@ Object {
"selectedLinearElement": null,
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"shouldRenderFrames": true,
"showHyperlinkPopup": false,
"showStats": false,
"showWelcomeScreen": true,

File diff suppressed because it is too large Load Diff

@ -39,6 +39,12 @@ Object {
"exportScale": 1,
"exportWithDarkMode": false,
"fileHandle": null,
"frameRendering": Object {
"clip": true,
"enabled": true,
"name": true,
"outline": true,
},
"frameToHighlight": null,
"gridSize": null,
"isBindingEnabled": true,
@ -70,7 +76,6 @@ Object {
"selectedLinearElement": null,
"selectionElement": null,
"shouldCacheIgnoreZoom": false,
"shouldRenderFrames": true,
"showHyperlinkPopup": false,
"showStats": false,
"showWelcomeScreen": false,

@ -115,7 +115,12 @@ export type AppState = {
startBoundElement: NonDeleted<ExcalidrawBindableElement> | null;
suggestedBindings: SuggestedBinding[];
frameToHighlight: NonDeleted<ExcalidrawFrameElement> | null;
shouldRenderFrames: boolean;
frameRendering: {
enabled: boolean;
name: boolean;
outline: boolean;
clip: boolean;
};
editingFrame: string | null;
elementsToHighlight: NonDeleted<ExcalidrawElement>[] | null;
// element being edited, but not necessarily added to elements array yet
@ -543,7 +548,7 @@ export type ExcalidrawImperativeAPI = {
* the frames are still interactive in edit mode. As such, this API should be
* used in conjunction with view mode (props.viewModeEnabled).
*/
toggleFrameRendering: InstanceType<typeof App>["toggleFrameRendering"];
updateFrameRendering: InstanceType<typeof App>["updateFrameRendering"];
};
export type Device = Readonly<{