diff --git a/README.md b/README.md index a18a2a8b..58c4e376 100644 --- a/README.md +++ b/README.md @@ -291,6 +291,13 @@ You may experience loss of parts of the image if set to `true` and you are expor Defaults to `false` +### waitForAnimationFrameAcquired + +When supplied, the library will wait for the next animation frame to be acquired before rendering the image. +This is useful when you want to achieve a smooth transition when rendering the image. + +Defaults to `false` + ### type A string indicating the image format. The default type is image/png; that type is also used if the given type isn't supported. diff --git a/src/clone-node.ts b/src/clone-node.ts index 5dfcd117..2e8bd964 100644 --- a/src/clone-node.ts +++ b/src/clone-node.ts @@ -9,12 +9,12 @@ import { import { getMimeType } from './mimes' import { resourceToDataURL } from './dataurl' -async function cloneCanvasElement(canvas: HTMLCanvasElement) { +async function cloneCanvasElement(canvas: HTMLCanvasElement, options: Options) { const dataURL = canvas.toDataURL() if (dataURL === 'data:,') { return canvas.cloneNode(false) as HTMLCanvasElement } - return createImage(dataURL) + return createImage(dataURL, options) } async function cloneVideoElement(video: HTMLVideoElement, options: Options) { @@ -25,13 +25,13 @@ async function cloneVideoElement(video: HTMLVideoElement, options: Options) { canvas.height = video.clientHeight ctx?.drawImage(video, 0, 0, canvas.width, canvas.height) const dataURL = canvas.toDataURL() - return createImage(dataURL) + return createImage(dataURL, options) } const poster = video.poster const contentType = getMimeType(poster) const dataURL = await resourceToDataURL(poster, contentType, options) - return createImage(dataURL) + return createImage(dataURL, options) } async function cloneIFrameElement(iframe: HTMLIFrameElement, options: Options) { @@ -55,7 +55,7 @@ async function cloneSingleNode( options: Options, ): Promise { if (isInstanceOfElement(node, HTMLCanvasElement)) { - return cloneCanvasElement(node) + return cloneCanvasElement(node, options) } if (isInstanceOfElement(node, HTMLVideoElement)) { diff --git a/src/index.ts b/src/index.ts index 2de59a30..b9aaba6b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -31,7 +31,7 @@ export async function toCanvas( ): Promise { const { width, height } = getImageSize(node, options) const svg = await toSvg(node, options) - const img = await createImage(svg) + const img = await createImage(svg, options) const canvas = document.createElement('canvas') const context = canvas.getContext('2d')! diff --git a/src/types.ts b/src/types.ts index 6023c3c2..ad81e8f4 100644 --- a/src/types.ts +++ b/src/types.ts @@ -86,6 +86,11 @@ export interface Options { * A boolean to turn off auto scaling for truly massive images.. */ skipAutoScale?: boolean + /** + * An option for rendering the image only when the image is visible on the frame. + * This might be useful for performance reasons when rendering a large number of images. + */ + waitForAnimationFrameAcquired?: boolean /** * A string indicating the image format. The default type is image/png; that type is also used if the given type isn't supported. */ diff --git a/src/util.ts b/src/util.ts index 3d430c8f..3361299b 100644 --- a/src/util.ts +++ b/src/util.ts @@ -196,12 +196,19 @@ export function canvasToBlob( }) } -export function createImage(url: string): Promise { +export function createImage( + url: string, + options: Options = {}, +): Promise { return new Promise((resolve, reject) => { const img = new Image() img.onload = () => { img.decode().then(() => { - requestAnimationFrame(() => resolve(img)) + if (options.waitForAnimationFrameAcquired) { + requestAnimationFrame(() => resolve(img)) + } else { + resolve(img) + } }) } img.onerror = reject