feat: Export API's to export the drawing to canvas, svg and blob (#3258)

* feat: Export utilities from package/utils

* update

* fix

* collapsible

* Update README.md

* update change

* update

* fix

* Apply suggestions from code review

Co-authored-by: David Luzar <luzar.david@gmail.com>

* Apply suggestions from code review

Co-authored-by: David Luzar <luzar.david@gmail.com>

* update

* Apply suggestions from code review

Co-authored-by: David Luzar <luzar.david@gmail.com>
This commit is contained in:
Aakansha Doshi 2021-03-16 22:21:56 +05:30 committed by GitHub
parent 84a1863233
commit edc62c550a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 117 additions and 11 deletions

View File

@ -18,6 +18,7 @@ Please add the latest change on the top under the correct section.
### Features ### Features
- Export API to export the drawing to canvas, svg and blob [#3258](https://github.com/excalidraw/excalidraw/pull/3258). For more info you can check the [readme](https://github.com/excalidraw/excalidraw/tree/master/src/packages/excalidraw/README.md#user-content-export-utils)
- Add a `theme` prop to indicate Excalidraw's theme. [#3228](https://github.com/excalidraw/excalidraw/pull/3228). When this prop is passed, the theme is fully controlled by host app. - Add a `theme` prop to indicate Excalidraw's theme. [#3228](https://github.com/excalidraw/excalidraw/pull/3228). When this prop is passed, the theme is fully controlled by host app.
- Support `libraryReturnUrl` prop to indicate what URL to install libraries to [#3227](https://github.com/excalidraw/excalidraw/pull/3227). - Support `libraryReturnUrl` prop to indicate what URL to install libraries to [#3227](https://github.com/excalidraw/excalidraw/pull/3227).

View File

@ -635,3 +635,93 @@ import { restore } from "@excalidraw/excalidraw";
``` ```
This function makes sure elements and state is set to appropriate values and set to default value if not present. It is combination of [restoreElements](#restoreElements) and [restoreAppState](#restoreAppState) This function makes sure elements and state is set to appropriate values and set to default value if not present. It is combination of [restoreElements](#restoreElements) and [restoreAppState](#restoreAppState)
**_The below APIs will be available in [next version](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/CHANGELOG.md#unreleased)_**
<details id="export-utils">
<summary><strong>Export utilities</strong></summary>
#### `exportToCanvas`
**_Signature_**
<pre
>exportToCanvas({
elements,
appState
getDimensions,
}: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/packages/utils.ts#L10">ExportOpts</a>
</pre>
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| elements | [Excalidraw Element []](https://github.com/excalidraw/excalidraw/blob/master/src/element/types) | | The elements to be exported to canvas |
| appState | [AppState](https://github.com/excalidraw/excalidraw/blob/master/src/packages/utils.ts#L12) | [defaultAppState](https://github.com/excalidraw/excalidraw/blob/master/src/appState.ts#L11) | The app state of the scene |
| getDimensions | `(width: number, height: number) => {width: number, height: number, scale: number)` | `(width, height) => ({ width, height, scale: 1 })` | A function which returns the width, height and scale with which canvas is to be exported. |
**How to use**
```js
import { exportToCanvas } from "@excalidraw/excalidraw";
```
This function returns the canvas with the exported elements, appState and dimensions.
#### `exportToBlob`
**_Signature_**
<pre>
exportToBlob(
opts: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/packages/utils.ts#L10">ExportOpts</a> & {
mimeType?: string,
quality?: number;
})
</pre>
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| opts | | | This param is passed to `exportToCanvas`. You can refer to [`exportToCanvas`](#exportToCanvas) |
| mimeType | string | "image/png" | Indicates the image format |
| quality | number | 0.92 | A value between 0 and 1 indicating the [image quality](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob#parameters). Applies only to `image/jpeg`/`image/webp` MIME types. |
**How to use**
```js
import { exportToBlob } from "@excalidraw/excalidraw";
```
Returns a promise which resolves with a [blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob). It internally uses [canvas.ToBlob](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob).
#### `exportToSvg`
**_Signature_**
<pre>
exportToSvg({
elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>,
appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L42">AppState</a>,
exportPadding?: number,
metadata?: string,
}
</pre>
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| elements | [Excalidraw Element []](https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78) | | The elements to exported as svg |
| appState | [AppState](https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L42) | [defaultAppState](https://github.com/excalidraw/excalidraw/blob/master/src/appState.ts#L11) | The app state of the scene |
| exportPadding | number | 10 | The padding to be added on canvas |
| metadata | string | '' | The metadata to be embedded in svg |
This function returns a svg with the exported elements.
##### Additional attributes of appState for `export\*` APIs
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| exportBackground | boolean | true | Indicates whether background should be exported |
| viewBackgroundColor | string | #fff | The default background color |
| shouldAddWatermark | boolean | false | Indicates whether watermark should be exported |
| exportWithDarkMode | boolean | false | Indicates whether to export with dark mode |
</details>

View File

@ -112,3 +112,8 @@ export {
} from "../../element"; } from "../../element";
export { defaultLang, languages } from "../../i18n"; export { defaultLang, languages } from "../../i18n";
export { restore, restoreAppState, restoreElements } from "../../data/restore"; export { restore, restoreAppState, restoreElements } from "../../data/restore";
export {
exportToCanvas,
exportToBlob,
exportToSvg,
} from "../../packages/utils";

View File

@ -6,10 +6,11 @@ import { getDefaultAppState } from "../appState";
import { AppState } from "../types"; import { AppState } from "../types";
import { ExcalidrawElement } from "../element/types"; import { ExcalidrawElement } from "../element/types";
import { getNonDeletedElements } from "../element"; import { getNonDeletedElements } from "../element";
import { restore } from "../data/restore";
type ExportOpts = { type ExportOpts = {
elements: readonly ExcalidrawElement[]; elements: readonly ExcalidrawElement[];
appState?: Omit<AppState, "offsetTop" | "offsetLeft">; appState?: Partial<Omit<AppState, "offsetTop" | "offsetLeft">>;
getDimensions: ( getDimensions: (
width: number, width: number,
height: number, height: number,
@ -18,17 +19,22 @@ type ExportOpts = {
export const exportToCanvas = ({ export const exportToCanvas = ({
elements, elements,
appState = getDefaultAppState(), appState,
getDimensions = (width, height) => ({ width, height, scale: 1 }), getDimensions = (width, height) => ({ width, height, scale: 1 }),
}: ExportOpts) => { }: ExportOpts) => {
const { elements: restoredElements, appState: restoredAppState } = restore(
{ elements, appState },
null,
);
const {
exportBackground,
viewBackgroundColor,
shouldAddWatermark,
} = restoredAppState;
return _exportToCanvas( return _exportToCanvas(
getNonDeletedElements(elements), getNonDeletedElements(restoredElements),
{ ...appState, offsetTop: 0, offsetLeft: 0 }, { ...restoredAppState, offsetTop: 0, offsetLeft: 0 },
{ { exportBackground, viewBackgroundColor, shouldAddWatermark },
exportBackground: appState.exportBackground ?? true,
viewBackgroundColor: appState.viewBackgroundColor ?? "#FFF",
shouldAddWatermark: appState.shouldAddWatermark ?? false,
},
(width: number, height: number) => { (width: number, height: number) => {
const canvas = document.createElement("canvas"); const canvas = document.createElement("canvas");
const ret = getDimensions(width, height); const ret = getDimensions(width, height);
@ -81,8 +87,12 @@ export const exportToSvg = ({
exportPadding?: number; exportPadding?: number;
metadata?: string; metadata?: string;
}): SVGSVGElement => { }): SVGSVGElement => {
return _exportToSvg(getNonDeletedElements(elements), { const { elements: restoredElements, appState: restoredAppState } = restore(
...appState, { elements, appState },
null,
);
return _exportToSvg(getNonDeletedElements(restoredElements), {
...restoredAppState,
exportPadding, exportPadding,
metadata, metadata,
}); });