/** * * @author Ray * * @date 2023-12-14 * * @workspace ray-template * * @remark 今天也是元气满满撸代码的一天 */ import domToImage from 'dom-to-image' import { unrefElement } from '@/utils' import type { Options as ReDomToImageOptions } from 'dom-to-image' import type { BasicTarget, TargetType } from '@/types' export type ImageType = keyof typeof domToImageMethods export type DomToImageResult = string | Blob | Uint8ClampedArray | undefined export interface UseDomToImageOptions extends ReDomToImageOptions { /** * * * 指定图片类型,允许传递 imageType 参数,用于指定图片类型 * * @default jpeg */ imageType?: ImageType /** * * * 在 dom 转换为图片之前执行 * * @param element current dom * * @default undefined */ beforeCreate?: (element: T | null | undefined) => void /** * * @param element current dom * @param result dom to image result * * 在 dom 转换为图片之后执行 * * @default undefined */ created?: (result: DomToImageResult, element: T) => void /** * * @param error dom to image error * * 在 dom 转换为图片失败时执行 * * @default undefined */ createdError?: (error?: Error) => void /** * * @param element current dom * * 无论 dom 转换为图片成功或失败,都会执行 * * @default undefined */ finally?: () => void } const domToImageMethods = { svg: domToImage.toSvg, png: domToImage.toPng, jpeg: domToImage.toJpeg, blob: domToImage.toBlob, pixelData: domToImage.toPixelData, } /** * * @param target ref dom * @param options dom-to-image options * * @see https://github.com/tsayen/dom-to-image * * @description * 使用 dom-to-image 将 dom 转换为图片,基于 dom-to-image v2.6.0。 * 拓展了 imageType 参数,用于指定图片类型。 * * create 方法支持在执行时传递 imageType 参数,用于指定图片类型。并且优先级大于 options.imageType; * 当然,你也可以不传递 imageType 参数,此时会使用 options.imageType, * 如果都未传递,则默认使用 jpeg。 * * @example * const refDom = ref() * const { create, stop } = useDomToImage(refDom, { * beforeCreate: (element) => { ... }, * created: (element, result) => { ... }, * createdError: (error) => { ... }, * finally: () => { ... }, * }) */ export const useDomToImage = ( target: BasicTarget, options?: UseDomToImageOptions, ) => { const { beforeCreate, created, createdError, finally: _finally, imageType: _imageType, } = options ?? {} const run = ( imageType?: UseDomToImageOptions['imageType'], ): Promise => { return new Promise((resolve, reject) => { const element = unrefElement(target) beforeCreate?.(element) if (!element) { createdError?.() return reject('useDomToImage: element is undefined.') } domToImageMethods[imageType ?? _imageType ?? 'jpeg']?.(element, options) .then((res) => { created?.(res, element) return resolve(res) }) .catch((error: Error) => { createdError?.(error) return reject(error) }) .finally(() => { _finally?.() }) }) } return { create: run, } } export type UseDomToImageReturnType = ReturnType