Skip to content

Commit

Permalink
export-wip
Browse files Browse the repository at this point in the history
  • Loading branch information
dwelle committed May 9, 2023
1 parent 35a1d0f commit 5d1c955
Show file tree
Hide file tree
Showing 20 changed files with 690 additions and 308 deletions.
6 changes: 3 additions & 3 deletions src/actions/actionClipboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
} from "../clipboard";
import { actionDeleteSelected } from "./actionDeleteSelected";
import { getSelectedElements } from "../scene/selection";
import { exportCanvas } from "../data/index";
import { exportAsImage } from "../data/index";
import { getNonDeletedElements, isTextElement } from "../element";
import { t } from "../i18n";

Expand Down Expand Up @@ -84,7 +84,7 @@ export const actionCopyAsSvg = register({
},
);
try {
await exportCanvas(
await exportAsImage(
"clipboard-svg",
selectedElements.length
? selectedElements
Expand Down Expand Up @@ -130,7 +130,7 @@ export const actionCopyAsPng = register({
},
);
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 @@ -54,6 +54,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 oc from "open-color";
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 @@ -89,10 +90,10 @@ export const getDefaultAppState = (): Omit<
editingFrame: null,
elementsToHighlight: null,
toast: null,
viewBackgroundColor: oc.white,
viewBackgroundColor: DEFAULT_BACKGROUND_COLOR,
zenModeEnabled: false,
zoom: {
value: 1 as NormalizedZoomValue,
value: DEFAULT_ZOOM_VALUE,
},
viewModeEnabled: false,
pendingImageElementId: null,
Expand Down
4 changes: 2 additions & 2 deletions src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1696,14 +1696,14 @@ class App extends React.Component<AppProps, AppState> {
{
elements: renderingElements,
appState: this.state,
scale: window.devicePixelRatio,
rc: this.rc!,
canvas: this.canvas!,
renderConfig: {
canvasScale: window.devicePixelRatio,
selectionColor,
scrollX: this.state.scrollX,
scrollY: this.state.scrollY,
viewBackgroundColor: this.state.viewBackgroundColor,
canvasBackgroundColor: this.state.viewBackgroundColor,
zoom: this.state.zoom,
remotePointerViewportCoords: pointerViewportCoords,
remotePointerButton: cursorButton,
Expand Down
19 changes: 14 additions & 5 deletions src/components/ImageExportDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,20 @@ const ImageExportModal = ({
return;
}
exportToCanvas({
elements: exportedElements,
appState,
files,
exportPadding,
maxWidthOrHeight: maxWidth,
data: {
elements: exportedElements,
appState,
files,
},
config: {
canvasBackgroundColor: !appState.exportBackground
? false
: appState.viewBackgroundColor,
padding: exportPadding,
theme: appState.exportWithDarkMode ? "dark" : "light",
scale: appState.exportScale,
maxWidthOrHeight: maxWidth,
},
})
.then((canvas) => {
setRenderError(null);
Expand Down
4 changes: 2 additions & 2 deletions src/components/LayerUI.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import clsx from "clsx";
import React from "react";
import { ActionManager } from "../actions/manager";
import { CLASSES, DEFAULT_SIDEBAR, LIBRARY_SIDEBAR_WIDTH } from "../constants";
import { exportCanvas } from "../data";
import { exportAsImage } from "../data";
import { isTextElement, showSelectedShapeActions } from "../element";
import { NonDeletedExcalidrawElement } from "../element/types";
import { Language, t } from "../i18n";
Expand Down Expand Up @@ -149,7 +149,7 @@ const LayerUI = ({
(type: ExportType): ExportCB =>
async (exportedElements) => {
trackEvent("export", type, "ui");
const fileHandle = await exportCanvas(
const fileHandle = await exportAsImage(
type,
exportedElements,
// FIXME once we split UI canvas from element canvas
Expand Down
12 changes: 7 additions & 5 deletions src/components/LibraryUnit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,14 @@ export const LibraryUnit = ({
return;
}
const svg = await exportToSvg({
elements,
appState: {
exportBackground: false,
viewBackgroundColor: oc.white,
data: {
elements,
appState: {
exportBackground: false,
viewBackgroundColor: oc.white,
},
files: null,
},
files: null,
});
svg.querySelector(".style-fonts")?.remove();
node.innerHTML = svg.outerHTML;
Expand Down
24 changes: 15 additions & 9 deletions src/components/PublishLibrary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,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 @@ -150,13 +154,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
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 oc from "open-color";

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

export const CLASSES = {
Expand Down Expand Up @@ -111,6 +112,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
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
46 changes: 27 additions & 19 deletions src/packages/excalidraw/example/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -253,10 +253,12 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
return false;
}
await exportToClipboard({
elements: excalidrawAPI.getSceneElements(),
appState: excalidrawAPI.getAppState(),
files: excalidrawAPI.getFiles(),
type,
data: {
elements: excalidrawAPI.getSceneElements(),
appState: excalidrawAPI.getAppState(),
files: excalidrawAPI.getFiles(),
},
type: "json",
});
window.alert(`Copied to clipboard as ${type} successfully`);
};
Expand Down Expand Up @@ -741,15 +743,17 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
return;
}
const svg = await exportToSvg({
elements: excalidrawAPI?.getSceneElements(),
appState: {
...initialData.appState,
exportWithDarkMode,
exportEmbedScene,
width: 300,
height: 100,
data: {
elements: excalidrawAPI?.getSceneElements(),
appState: {
...initialData.appState,
exportWithDarkMode,
exportEmbedScene,
width: 300,
height: 100,
},
files: excalidrawAPI?.getFiles(),
},
files: excalidrawAPI?.getFiles(),
});
appRef.current.querySelector(".export-svg").innerHTML =
svg.outerHTML;
Expand All @@ -765,14 +769,18 @@ export default function App({ appTitle, useCustom, customArgs }: AppProps) {
return;
}
const blob = await exportToBlob({
elements: excalidrawAPI?.getSceneElements(),
mimeType: "image/png",
appState: {
...initialData.appState,
exportEmbedScene,
exportWithDarkMode,
data: {
elements: excalidrawAPI?.getSceneElements(),
appState: {
...initialData.appState,
exportEmbedScene,
exportWithDarkMode,
},
files: excalidrawAPI?.getFiles(),
},
config: {
mimeType: "image/png",
},
files: excalidrawAPI?.getFiles(),
});
setBlobUrl(window.URL.createObjectURL(blob));
}}
Expand Down
Loading

0 comments on commit 5d1c955

Please sign in to comment.