Skip to content

Commit

Permalink
[wip] export utils
Browse files Browse the repository at this point in the history
  • Loading branch information
dwelle committed Sep 29, 2023
1 parent d23cbd3 commit d27af2e
Show file tree
Hide file tree
Showing 21 changed files with 735 additions and 330 deletions.
6 changes: 3 additions & 3 deletions src/actions/actionClipboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
probablySupportsClipboardWriteText,
} from "../clipboard";
import { actionDeleteSelected } from "./actionDeleteSelected";
import { exportCanvas } from "../data/index";
import { exportAsImage } from "../data/index";
import { getNonDeletedElements, isTextElement } from "../element";
import { t } from "../i18n";

Expand Down Expand Up @@ -81,7 +81,7 @@ export const actionCopyAsSvg = register({
includeElementsInFrames: true,
});
try {
await exportCanvas(
await exportAsImage(
"clipboard-svg",
selectedElements.length
? selectedElements
Expand Down Expand Up @@ -125,7 +125,7 @@ export const actionCopyAsPng = register({
includeElementsInFrames: true,
});
try {
await exportCanvas(
await exportAsImage(
"clipboard",
selectedElements.length
? selectedElements
Expand Down
16 changes: 14 additions & 2 deletions src/actions/actionExport.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ import { useDevice } from "../components/App";
import { KEYS } from "../keys";
import { register } from "./register";
import { CheckboxItem } from "../components/CheckboxItem";
import { getExportSize } from "../scene/export";
import { getCanvasSize } from "../scene/export";
import { DEFAULT_EXPORT_PADDING, EXPORT_SCALES, THEME } from "../constants";
import { getSelectedElements, isSomeElementSelected } from "../scene";
import { getNonDeletedElements } from "../element";
import { isImageFileHandle } from "../data/blob";
import { nativeFileSystemSupported } from "../data/filesystem";
import { Theme } from "../element/types";
import { NonDeletedExcalidrawElement, Theme } from "../element/types";

import "../components/ToolIcon.scss";

Expand Down Expand Up @@ -55,6 +55,18 @@ export const actionChangeExportScale = register({
? getSelectedElements(elements, appState)
: elements;

const getExportSize = (
elements: readonly NonDeletedExcalidrawElement[],
padding: number,
scale: number,
): [number, number] => {
const [, , width, height] = getCanvasSize(elements).map((dimension) =>
Math.trunc(dimension * scale),
);

return [width + padding * 2, height + padding * 2];
};

return (
<>
{EXPORT_SCALES.map((s) => {
Expand Down
9 changes: 5 additions & 4 deletions src/appState.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { COLOR_PALETTE } from "./colors";
import {
DEFAULT_BACKGROUND_COLOR,
DEFAULT_ELEMENT_PROPS,
DEFAULT_FONT_FAMILY,
DEFAULT_FONT_SIZE,
DEFAULT_TEXT_ALIGN,
DEFAULT_ZOOM_VALUE,
EXPORT_SCALES,
THEME,
} from "./constants";
import { t } from "./i18n";
import { AppState, NormalizedZoomValue } from "./types";
import { AppState } from "./types";
import { getDateTime } from "./utils";

const defaultExportScale = EXPORT_SCALES.includes(devicePixelRatio)
Expand Down Expand Up @@ -90,10 +91,10 @@ export const getDefaultAppState = (): Omit<
editingFrame: null,
elementsToHighlight: null,
toast: null,
viewBackgroundColor: COLOR_PALETTE.white,
viewBackgroundColor: DEFAULT_BACKGROUND_COLOR,
zenModeEnabled: false,
zoom: {
value: 1 as NormalizedZoomValue,
value: DEFAULT_ZOOM_VALUE,
},
viewModeEnabled: false,
pendingImageElementId: null,
Expand Down
6 changes: 4 additions & 2 deletions src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ import {
ZOOM_STEP,
POINTER_EVENTS,
} from "../constants";
import { exportCanvas, loadFromBlob } from "../data";
import { exportAsImage, loadFromBlob } from "../data";
import Library, { distributeLibraryItemsOnSquareGrid } from "../data/library";
import { restore, restoreElements } from "../data/restore";
import {
Expand Down Expand Up @@ -1285,6 +1285,8 @@ class App extends React.Component<AppProps, AppState> {
imageCache: this.imageCache,
isExporting: false,
renderGrid: true,
canvasBackgroundColor:
this.state.viewBackgroundColor,
}}
/>
<InteractiveCanvas
Expand Down Expand Up @@ -1350,7 +1352,7 @@ class App extends React.Component<AppProps, AppState> {
elements: readonly NonDeletedExcalidrawElement[],
) => {
trackEvent("export", type, "ui");
const fileHandle = await exportCanvas(
const fileHandle = await exportAsImage(
type,
elements,
this.state,
Expand Down
19 changes: 14 additions & 5 deletions src/components/ImageExportDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,20 @@ const ImageExportModal = ({
return;
}
exportToCanvas({
elements: exportedElements,
appState,
files,
exportPadding: DEFAULT_EXPORT_PADDING,
maxWidthOrHeight: Math.max(maxWidth, maxHeight),
data: {
elements: exportedElements,
appState,
files,
},
config: {
canvasBackgroundColor: !appState.exportBackground
? false
: appState.viewBackgroundColor,
padding: DEFAULT_EXPORT_PADDING,
theme: appState.exportWithDarkMode ? "dark" : "light",
scale: appState.exportScale,
maxWidthOrHeight: Math.max(maxWidth, maxHeight),
},
})
.then((canvas) => {
setRenderError(null);
Expand Down
24 changes: 15 additions & 9 deletions src/components/PublishLibrary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,13 @@ const generatePreviewImage = async (libraryItems: LibraryItems) => {
// ---------------------------------------------------------------------------
for (const [index, item] of libraryItems.entries()) {
const itemCanvas = await exportToCanvas({
elements: item.elements,
files: null,
maxWidthOrHeight: BOX_SIZE,
data: {
elements: item.elements,
files: null,
},
config: {
maxWidthOrHeight: BOX_SIZE,
},
});

const { width, height } = itemCanvas;
Expand Down Expand Up @@ -151,13 +155,15 @@ const SingleLibraryItem = ({
}
(async () => {
const svg = await exportToSvg({
elements: libItem.elements,
appState: {
...appState,
viewBackgroundColor: OpenColor.white,
exportBackground: true,
data: {
elements: libItem.elements,
appState: {
...appState,
viewBackgroundColor: OpenColor.white,
exportBackground: true,
},
files: null,
},
files: null,
});
node.innerHTML = svg.outerHTML;
})();
Expand Down
1 change: 0 additions & 1 deletion src/components/canvases/StaticCanvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ const getRelevantAppStateProps = (
theme: appState.theme,
pendingImageElementId: appState.pendingImageElementId,
shouldCacheIgnoreZoom: appState.shouldCacheIgnoreZoom,
viewBackgroundColor: appState.viewBackgroundColor,
exportScale: appState.exportScale,
selectedElementsAreBeingDragged: appState.selectedElementsAreBeingDragged,
gridSize: appState.gridSize,
Expand Down
6 changes: 5 additions & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import cssVariables from "./css/variables.module.scss";
import { AppProps } from "./types";
import { AppProps, NormalizedZoomValue } from "./types";
import { ExcalidrawElement, FontFamilyValues } from "./element/types";
import { COLOR_PALETTE } from "./colors";

Expand Down Expand Up @@ -94,6 +94,7 @@ export const YOUTUBE_STATES = {
export const ENV = {
TEST: "test",
DEVELOPMENT: "development",
PRODUCTION: "production",
};

export const CLASSES = {
Expand Down Expand Up @@ -131,6 +132,9 @@ export const DEFAULT_FONT_FAMILY: FontFamilyValues = FONT_FAMILY.Virgil;
export const DEFAULT_TEXT_ALIGN = "left";
export const DEFAULT_VERTICAL_ALIGN = "top";
export const DEFAULT_VERSION = "{version}";
export const DEFAULT_BACKGROUND_COLOR = "#ffffff";
export const DEFAULT_STROKE_COLOR = "#000000";
export const DEFAULT_ZOOM_VALUE = 1 as NormalizedZoomValue;

export const CANVAS_ONLY_ACTIONS = ["selectAll"];

Expand Down
19 changes: 14 additions & 5 deletions src/data/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { serializeAsJSON } from "./json";
export { loadFromBlob } from "./blob";
export { loadFromJSON, saveAsJSON } from "./json";

export const exportCanvas = async (
export const exportAsImage = async (
type: Omit<ExportType, "backend">,
elements: readonly NonDeletedExcalidrawElement[],
appState: AppState,
Expand Down Expand Up @@ -66,10 +66,19 @@ export const exportCanvas = async (
}
}

const tempCanvas = await exportToCanvas(elements, appState, files, {
exportBackground,
viewBackgroundColor,
exportPadding,
const tempCanvas = await exportToCanvas({
data: {
elements,
appState,
files,
},
config: {
canvasBackgroundColor: !exportBackground ? false : viewBackgroundColor,
padding: exportPadding,
theme: appState.exportWithDarkMode ? "dark" : "light",
scale: appState.exportScale,
fit: "none",
},
});
tempCanvas.style.display = "none";
document.body.appendChild(tempCanvas);
Expand Down
4 changes: 2 additions & 2 deletions src/data/resave.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ExcalidrawElement } from "../element/types";
import { AppState, BinaryFiles } from "../types";
import { exportCanvas } from ".";
import { exportAsImage } from ".";
import { getNonDeletedElements } from "../element";
import { getFileHandleType, isImageFileHandleType } from "./blob";

Expand All @@ -23,7 +23,7 @@ export const resaveAsImageWithScene = async (
exportEmbedScene: true,
};

await exportCanvas(
await exportAsImage(
fileHandleType,
getNonDeletedElements(elements),
appState,
Expand Down
16 changes: 10 additions & 6 deletions src/hooks/useLibraryItemSvg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@ export const libraryItemSvgsCache = atom<SvgCache>(new Map());

const exportLibraryItemToSvg = async (elements: LibraryItem["elements"]) => {
return await exportToSvg({
elements,
appState: {
exportBackground: false,
viewBackgroundColor: COLOR_PALETTE.white,
data: {
elements,
appState: {
exportBackground: false,
viewBackgroundColor: COLOR_PALETTE.white,
},
files: null,
},
config: {
// renderEmbeddables: false,
},
files: null,
renderEmbeddables: false,
});
};

Expand Down
27 changes: 13 additions & 14 deletions src/index-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,22 +57,21 @@ const elements = [
registerFont("./public/Virgil.woff2", { family: "Virgil" });
registerFont("./public/Cascadia.woff2", { family: "Cascadia" });

const canvas = exportToCanvas(
elements as any,
{
...getDefaultAppState(),
offsetTop: 0,
offsetLeft: 0,
width: 0,
height: 0,
const canvas = exportToCanvas({
data: {
elements: elements as any,
appState: {
...getDefaultAppState(),
width: 0,
height: 0,
},
files: {}, // files
},
{}, // files
{
exportBackground: true,
viewBackgroundColor: "#ffffff",
config: {
canvasBackgroundColor: "#ffffff",
createCanvas,
},
createCanvas,
);
});

const fs = require("fs");
const out = fs.createWriteStream("test.png");
Expand Down
Loading

0 comments on commit d27af2e

Please sign in to comment.