utils.ts 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import {
  2. exportToCanvas as _exportToCanvas,
  3. exportToSvg as _exportToSvg,
  4. } from "../scene/export";
  5. import { getDefaultAppState } from "../appState";
  6. import { AppState } from "../types";
  7. import { ExcalidrawElement } from "../element/types";
  8. import { getNonDeletedElements } from "../element";
  9. import { restore } from "../data/restore";
  10. type ExportOpts = {
  11. elements: readonly ExcalidrawElement[];
  12. appState?: Partial<Omit<AppState, "offsetTop" | "offsetLeft">>;
  13. getDimensions?: (
  14. width: number,
  15. height: number,
  16. ) => { width: number; height: number; scale: number };
  17. };
  18. export const exportToCanvas = ({
  19. elements,
  20. appState,
  21. getDimensions = (width, height) => ({ width, height, scale: 1 }),
  22. }: ExportOpts) => {
  23. const { elements: restoredElements, appState: restoredAppState } = restore(
  24. { elements, appState },
  25. null,
  26. );
  27. const {
  28. exportBackground,
  29. viewBackgroundColor,
  30. shouldAddWatermark,
  31. } = restoredAppState;
  32. return _exportToCanvas(
  33. getNonDeletedElements(restoredElements),
  34. { ...restoredAppState, offsetTop: 0, offsetLeft: 0, width: 0, height: 0 },
  35. { exportBackground, viewBackgroundColor, shouldAddWatermark },
  36. (width: number, height: number) => {
  37. const canvas = document.createElement("canvas");
  38. const ret = getDimensions(width, height);
  39. canvas.width = ret.width;
  40. canvas.height = ret.height;
  41. return { canvas, scale: ret.scale };
  42. },
  43. );
  44. };
  45. export const exportToBlob = (
  46. opts: ExportOpts & {
  47. mimeType?: string;
  48. quality?: number;
  49. },
  50. ): Promise<Blob | null> => {
  51. const canvas = exportToCanvas(opts);
  52. let { mimeType = "image/png", quality } = opts;
  53. if (mimeType === "image/png" && typeof quality === "number") {
  54. console.warn(`"quality" will be ignored for "image/png" mimeType`);
  55. }
  56. if (mimeType === "image/jpg") {
  57. mimeType = "image/jpeg";
  58. }
  59. quality = quality ? quality : /image\/jpe?g/.test(mimeType) ? 0.92 : 0.8;
  60. return new Promise((resolve) => {
  61. canvas.toBlob(
  62. (blob: Blob | null) => {
  63. resolve(blob);
  64. },
  65. mimeType,
  66. quality,
  67. );
  68. });
  69. };
  70. export const exportToSvg = ({
  71. elements,
  72. appState = getDefaultAppState(),
  73. exportPadding,
  74. metadata,
  75. }: Omit<ExportOpts, "getDimensions"> & {
  76. exportPadding?: number;
  77. metadata?: string;
  78. }): SVGSVGElement => {
  79. const { elements: restoredElements, appState: restoredAppState } = restore(
  80. { elements, appState },
  81. null,
  82. );
  83. return _exportToSvg(getNonDeletedElements(restoredElements), {
  84. ...restoredAppState,
  85. exportPadding,
  86. metadata,
  87. });
  88. };