瀏覽代碼

feat: embed scene support for png export in npm package (#5047)

* feat: embed scene support for png export in npm package

* move logic to the callback function

* add exportEmbedScene checkbox in package example

* update readme and changelog

* add PR link in changelog

* reverse sort changelog items
Achille Lacoin 3 年之前
父節點
當前提交
3840e2f4e6

+ 2 - 1
src/packages/excalidraw/CHANGELOG.md

@@ -17,7 +17,8 @@ Please add the latest change on the top under the correct section.
 
 #### Features
 
-- Exported [`restoreLibraryItems`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#restoreLibraryItems) API useful when dealing with libraries [#4995](https://github.com/excalidraw/excalidraw/pull/4995).
+- The `exportToBlob` utility now supports the `exportEmbedScene` option when generating a png image [#5047](https://github.com/excalidraw/excalidraw/pull/5047).
+- Exported [`restoreLibraryItems`](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#restoreLibraryItems) API [#4995](https://github.com/excalidraw/excalidraw/pull/4995).
 
 #### Fixes
 

+ 1 - 1
src/packages/excalidraw/README_NEXT.md

@@ -907,7 +907,7 @@ This function returns a promise which resolves to svg of the exported drawing.
 | exportBackground | boolean | true | Indicates whether background should be exported |
 | viewBackgroundColor | string | #fff | The default background color |
 | exportWithDarkMode | boolean | false | Indicates whether to export with dark mode |
-| exportEmbedScene | boolean | false | Indicates whether scene data should be embedded in svg. This will increase the svg size. |
+| exportEmbedScene | boolean | false | Indicates whether scene data should be embedded in svg/png. This will increase the image size. |
 
 ### Extra API's
 

+ 11 - 0
src/packages/excalidraw/example/App.js

@@ -51,6 +51,7 @@ export default function App() {
   const [blobUrl, setBlobUrl] = useState(null);
   const [canvasUrl, setCanvasUrl] = useState(null);
   const [exportWithDarkMode, setExportWithDarkMode] = useState(false);
+  const [exportEmbedScene, setExportEmbedScene] = useState(false);
   const [theme, setTheme] = useState("light");
 
   const initialStatePromiseRef = useRef({ promise: null });
@@ -245,6 +246,14 @@ export default function App() {
             />
             Export with dark mode
           </label>
+          <label className="export-wrapper__checkbox">
+            <input
+              type="checkbox"
+              checked={exportEmbedScene}
+              onChange={() => setExportEmbedScene(!exportEmbedScene)}
+            />
+            Export with embed scene
+          </label>
           <button
             onClick={async () => {
               const svg = await exportToSvg({
@@ -252,6 +261,7 @@ export default function App() {
                 appState: {
                   ...initialData.appState,
                   exportWithDarkMode,
+                  exportEmbedScene,
                   width: 300,
                   height: 100,
                 },
@@ -272,6 +282,7 @@ export default function App() {
                 mimeType: "image/png",
                 appState: {
                   ...initialData.appState,
+                  exportEmbedScene,
                   exportWithDarkMode,
                 },
                 files: excalidrawRef.current.getFiles(),

+ 18 - 1
src/packages/utils.ts

@@ -8,6 +8,8 @@ import { ExcalidrawElement, NonDeleted } from "../element/types";
 import { getNonDeletedElements } from "../element";
 import { restore } from "../data/restore";
 import { MIME_TYPES } from "../constants";
+import { encodePngMetadata } from "../data/image";
+import { serializeAsJSON } from "../data/json";
 
 type ExportOpts = {
   elements: readonly NonDeleted<ExcalidrawElement>[];
@@ -107,7 +109,22 @@ export const exportToBlob = async (
 
   return new Promise((resolve) => {
     canvas.toBlob(
-      (blob: Blob | null) => {
+      async (blob: Blob | null) => {
+        if (
+          blob &&
+          mimeType === MIME_TYPES.png &&
+          opts.appState?.exportEmbedScene
+        ) {
+          blob = await encodePngMetadata({
+            blob,
+            metadata: serializeAsJSON(
+              opts.elements,
+              opts.appState,
+              opts.files || {},
+              "local",
+            ),
+          });
+        }
         resolve(blob);
       },
       mimeType,