UNPKG

fabric

Version:

Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.

1 lines 8.87 kB
{"version":3,"file":"objectEnlive.min.mjs","sources":["../../../../src/util/misc/objectEnlive.ts"],"sourcesContent":["import { noop } from '../../constants';\nimport type { FabricObject } from '../../shapes/Object/FabricObject';\nimport type {\n Abortable,\n Constructor,\n TCrossOrigin,\n TFiller,\n} from '../../typedefs';\nimport { createImage } from './dom';\nimport { classRegistry } from '../../ClassRegistry';\nimport type { BaseFilter } from '../../filters/BaseFilter';\nimport type { FabricObject as BaseFabricObject } from '../../shapes/Object/Object';\nimport { FabricError, SignalAbortedError } from '../internals/console';\nimport type { Shadow } from '../../Shadow';\n\nexport type LoadImageOptions = Abortable & {\n /**\n * cors value for the image loading, default to anonymous\n */\n crossOrigin?: TCrossOrigin;\n};\n\n/**\n * Loads image element from given url and resolve it, or catch.\n * @param {String} url URL representing an image\n * @param {LoadImageOptions} [options] image loading options\n * @returns {Promise<HTMLImageElement>} the loaded image.\n */\nexport const loadImage = (\n url: string,\n { signal, crossOrigin = null }: LoadImageOptions = {},\n) =>\n new Promise<HTMLImageElement>(function (resolve, reject) {\n if (signal && signal.aborted) {\n return reject(new SignalAbortedError('loadImage'));\n }\n const img = createImage();\n let abort: EventListenerOrEventListenerObject;\n if (signal) {\n abort = function (err: Event) {\n img.src = '';\n reject(err);\n };\n signal.addEventListener('abort', abort, { once: true });\n }\n const done = function () {\n img.onload = img.onerror = null;\n abort && signal?.removeEventListener('abort', abort);\n resolve(img);\n };\n if (!url) {\n done();\n return;\n }\n img.onload = done;\n img.onerror = function () {\n abort && signal?.removeEventListener('abort', abort);\n reject(new FabricError(`Error loading ${img.src}`));\n };\n crossOrigin && (img.crossOrigin = crossOrigin);\n img.src = url;\n });\n\nexport type EnlivenObjectOptions = Abortable & {\n /**\n * Method for further parsing of object elements,\n * called after each fabric object created.\n */\n reviver?: <\n T extends\n | BaseFabricObject\n | FabricObject\n | BaseFilter<string>\n | Shadow\n | TFiller,\n >(\n serializedObj: Record<string, any>,\n instance: T,\n ) => void;\n};\n\n/**\n * @TODO type this correctly.\n * Creates corresponding fabric instances from their object representations\n * @param {Object[]} objects Objects to enliven\n * @param {EnlivenObjectOptions} [options]\n * @param {(serializedObj: object, instance: FabricObject) => any} [options.reviver] Method for further parsing of object elements,\n * called after each fabric object created.\n * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n * @returns {Promise<FabricObject[]>}\n */\nexport const enlivenObjects = <\n T extends\n | BaseFabricObject\n | FabricObject\n | BaseFilter<string>\n | Shadow\n | TFiller,\n>(\n objects: any[],\n { signal, reviver = noop }: EnlivenObjectOptions = {},\n) =>\n new Promise<T[]>((resolve, reject) => {\n const instances: T[] = [];\n signal && signal.addEventListener('abort', reject, { once: true });\n Promise.all(\n objects.map((obj) =>\n classRegistry\n .getClass<\n Constructor<T> & {\n fromObject(options: any, context: Abortable): Promise<T>;\n }\n >(obj.type)\n .fromObject(obj, { signal })\n .then((fabricInstance) => {\n reviver(obj, fabricInstance);\n instances.push(fabricInstance);\n return fabricInstance;\n }),\n ),\n )\n .then(resolve)\n .catch((error) => {\n // cleanup\n instances.forEach((instance) => {\n (instance as FabricObject).dispose &&\n (instance as FabricObject).dispose();\n });\n reject(error);\n })\n .finally(() => {\n signal && signal.removeEventListener('abort', reject);\n });\n });\n\n/**\n * Creates corresponding fabric instances residing in an object, e.g. `clipPath`\n * @param {Object} object with properties to enlive ( fill, stroke, clipPath, path )\n * @param {object} [options]\n * @param {AbortSignal} [options.signal] handle aborting, see https://developer.mozilla.org/en-US/docs/Web/API/AbortController/signal\n * @returns {Promise<Record<string, FabricObject | TFiller | null>>} the input object with enlived values\n */\nexport const enlivenObjectEnlivables = <\n R = Record<string, FabricObject | TFiller | null>,\n>(\n serializedObject: any,\n { signal }: Abortable = {},\n) =>\n new Promise<R>((resolve, reject) => {\n const instances: (FabricObject | TFiller | Shadow)[] = [];\n signal && signal.addEventListener('abort', reject, { once: true });\n // enlive every possible property\n const promises = Object.values(serializedObject).map((value: any) => {\n if (!value) {\n return value;\n }\n /**\n * clipPath or shadow or gradient or text on a path or a pattern,\n * or the backgroundImage or overlayImage of canvas\n * If we have a type and there is a classe registered for it, we enlive it.\n * If there is no class registered for it we return the value as is\n * */\n if (value.type && classRegistry.has(value.type)) {\n return enlivenObjects<FabricObject | Shadow | TFiller>([value], {\n signal,\n }).then(([enlived]) => {\n instances.push(enlived);\n return enlived;\n });\n }\n return value;\n });\n const keys = Object.keys(serializedObject);\n Promise.all(promises)\n .then((enlived) => {\n return enlived.reduce((acc, instance, index) => {\n acc[keys[index]] = instance;\n return acc;\n }, {});\n })\n .then(resolve)\n .catch((error) => {\n // cleanup\n instances.forEach((instance: any) => {\n instance.dispose && instance.dispose();\n });\n reject(error);\n })\n .finally(() => {\n signal && signal.removeEventListener('abort', reject);\n });\n });\n"],"names":["loadImage","url","signal","crossOrigin","arguments","length","undefined","Promise","resolve","reject","aborted","SignalAbortedError","img","createImage","abort","err","src","addEventListener","once","done","onload","onerror","removeEventListener","FabricError","concat","enlivenObjects","objects","reviver","noop","instances","all","map","obj","classRegistry","getClass","type","fromObject","then","fabricInstance","push","catch","error","forEach","instance","dispose","finally","enlivenObjectEnlivables","serializedObject","promises","Object","values","value","has","_ref","enlived","keys","reduce","acc","index"],"mappings":"0OA4BaA,MAAAA,EAAY,SACvBC,GAAW,IACXC,OAAEA,EAAMC,YAAEA,EAAc,MAAwBC,UAAAC,OAAAD,QAAAE,IAAAF,UAAAE,GAAAF,UAAG,GAAA,GAAE,OAErD,IAAIG,SAA0B,SAAUC,EAASC,GAC/C,GAAIP,GAAUA,EAAOQ,QACnB,OAAOD,EAAO,IAAIE,EAAmB,cAEvC,MAAMC,EAAMC,IACZ,IAAIC,EACAZ,IACFY,EAAQ,SAAUC,GAChBH,EAAII,IAAM,GACVP,EAAOM,IAETb,EAAOe,iBAAiB,QAASH,EAAO,CAAEI,MAAM,KAElD,MAAMC,EAAO,WACXP,EAAIQ,OAASR,EAAIS,QAAU,KAC3BP,IAASZ,SAAAA,EAAQoB,oBAAoB,QAASR,IAC9CN,EAAQI,IAELX,GAILW,EAAIQ,OAASD,EACbP,EAAIS,QAAU,WACZP,IAASZ,SAAAA,EAAQoB,oBAAoB,QAASR,IAC9CL,EAAO,IAAIc,EAAWC,iBAAAA,OAAkBZ,EAAII,QAE9Cb,IAAgBS,EAAIT,YAAcA,GAClCS,EAAII,IAAMf,GATRkB,GAUJ,GAAE,EA8BSM,EAAiB,SAQ5BC,GAAc,IACdxB,OAAEA,EAAMyB,QAAEA,EAAUC,GAA4BxB,UAAAC,OAAAD,QAAAE,IAAAF,UAAAE,GAAAF,UAAG,GAAA,GAAE,OAErD,IAAIG,SAAa,CAACC,EAASC,KACzB,MAAMoB,EAAiB,GACvB3B,GAAUA,EAAOe,iBAAiB,QAASR,EAAQ,CAAES,MAAM,IAC3DX,QAAQuB,IACNJ,EAAQK,KAAKC,GACXC,EACGC,SAICF,EAAIG,MACLC,WAAWJ,EAAK,CAAE9B,WAClBmC,MAAMC,IACLX,EAAQK,EAAKM,GACbT,EAAUU,KAAKD,GACRA,QAIZD,KAAK7B,GACLgC,OAAOC,IAENZ,EAAUa,SAASC,IAChBA,EAA0BC,SACxBD,EAA0BC,SAAS,IAExCnC,EAAOgC,EAAM,IAEdI,SAAQ,KACP3C,GAAUA,EAAOoB,oBAAoB,QAASb,EAAO,GACrD,GACJ,EASSqC,EAA0B,SAGrCC,GAAqB,IACrB7C,OAAEA,GAAmBE,UAAAC,OAAAD,QAAAE,IAAAF,UAAAE,GAAAF,UAAG,GAAA,GAAE,OAE1B,IAAIG,SAAW,CAACC,EAASC,KACvB,MAAMoB,EAAiD,GACvD3B,GAAUA,EAAOe,iBAAiB,QAASR,EAAQ,CAAES,MAAM,IAE3D,MAAM8B,EAAWC,OAAOC,OAAOH,GAAkBhB,KAAKoB,GAC/CA,GASDA,EAAMhB,MAAQF,EAAcmB,IAAID,EAAMhB,MACjCV,EAAgD,CAAC0B,GAAQ,CAC9DjD,WACCmC,MAAKgB,IAAe,IAAbC,GAAQD,EAEhB,OADAxB,EAAUU,KAAKe,GACRA,CAAO,IAbTH,IAkBLI,EAAON,OAAOM,KAAKR,GACzBxC,QAAQuB,IAAIkB,GACTX,MAAMiB,GACEA,EAAQE,QAAO,CAACC,EAAKd,EAAUe,KACpCD,EAAIF,EAAKG,IAAUf,EACZc,IACN,CAAE,KAENpB,KAAK7B,GACLgC,OAAOC,IAENZ,EAAUa,SAASC,IACjBA,EAASC,SAAWD,EAASC,SAAS,IAExCnC,EAAOgC,EAAM,IAEdI,SAAQ,KACP3C,GAAUA,EAAOoB,oBAAoB,QAASb,EAAO,GACrD,GACJ"}