custom-svga 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var F=typeof document<"u"?document.currentScript:null,d=(n=>(n.INIT="init",n.VISIBILITY="visibility",n.SET_MOVIE="setMovie",n.SET_IMAGE="setImage",n.SET_DYNAMIC_TEXT="setDynamicText",n.DRAW_EXTERNAL_POSTER="drawExternalPoster",n.PLAY="play",n.STOP="stop",n.PAUSE="pause",n.STEP_TO_FRAME="stepToFrame",n.STEP_TO_PERCENTAGE="stepToPercentage",n.CLEAR="clear",n.CLEAR_DYNAMIC_OBJECTS="clearDynamicObjects",n.CLEAR_DYNAMIC_OBJECT="clearDynamicObject",n.DESTROY="destroy",n.PARSE="parse",n.PARSE_OFFSCREEN="parse_offscreen",n.RELEASE_CACHE="releaseCache",n))(d||{}),k=(n=>(n.SUCCESS="SUCCESS",n.ERROR="ERROR",n.EVENT="event",n))(k||{}),g=(n=>(n.READY="ready",n.ON_START="onStart",n.ON_STOP="onStop",n.ON_PAUSE="onPause",n.ON_PROCESS="onProcess",n.ON_LOOP_END="onLoopEnd",n.ON_REQUEST_MOVIE_DATA="onRequestMovieData",n))(g||{});let w=null,D=null;const R=new Map;let W=0,C={};function Y(n){C={...C,...n}}const x=new Map;let L=null;function G(n){L=n}function I(){if(!w){if(C.workerCreator)w=C.workerCreator();else if(C.workerUrl)w=new Worker(C.workerUrl);else{let n;try{typeof{url:typeof document>"u"?require("url").pathToFileURL(__filename).href:F&&F.tagName.toUpperCase()==="SCRIPT"&&F.src||new URL("index.cjs",document.baseURI).href}<"u"&&(typeof document>"u"?require("url").pathToFileURL(__filename).href:F&&F.tagName.toUpperCase()==="SCRIPT"&&F.src||new URL("index.cjs",document.baseURI).href)?n=new URL("./svga.worker.ts",typeof document>"u"?require("url").pathToFileURL(__filename).href:F&&F.tagName.toUpperCase()==="SCRIPT"&&F.src||new URL("index.cjs",document.baseURI).href):n="./svga.worker.ts"}catch{n="./svga.worker.ts"}w=new Worker(n,{type:"module"})}w.onmessage=n=>{const{type:e,id:t,name:s,args:a,taskId:i}=n.data;if(i!==void 0){L&&L(n.data);return}const r=R.get(t);r&&e===k.EVENT&&(s===g.ON_START&&r.onStart?r.onStart():s===g.ON_STOP&&r.onStop?r.onStop():s===g.ON_PAUSE&&r.onPause?r.onPause():s===g.ON_LOOP_END&&r.onLoopEnd?r.onLoopEnd():s===g.ON_PROCESS&&r.onProcess?r.onProcess(a[0]):s===g.ON_REQUEST_MOVIE_DATA&&r.resendMovieData())}}return w}class V{id;canvas;observerIsVisible=!0;worker;onStart;onPause;onStop;onLoopEnd;onProcess;_dynamicKeys=new Set;_config;_shapeRendererInstance=null;_movieData=null;constructor(e,t){this.canvas=e,this.id=`renderer_${W++}`,this._config=Object.assign({loop:0,useIntersectionObserver:!0,useSharedRAF:!0,invisibleBehavior:"pause"},t),R.set(this.id,this),this.worker=I();const s=e.transferControlToOffscreen();this.worker.postMessage({type:d.INIT,id:this.id,canvas:s,config:this._config},[s]),this._config.useIntersectionObserver!==!1&&(!D&&typeof IntersectionObserver<"u"&&(D=new IntersectionObserver(a=>{a.forEach(i=>{Array.from(R.values()).filter(r=>r.canvas===i.target).forEach(r=>{r.observerIsVisible=i.isIntersecting,r.worker.postMessage({type:d.VISIBILITY,id:r.id,visible:r.observerIsVisible})})})})),D&&D.observe(this.canvas))}async resendMovieData(){if(this._movieData){const e=this._movieData.movieDataId||"movie_direct_"+Math.random().toString(36).substring(2)+Date.now(),t={},s=[];if(typeof createImageBitmap<"u"&&this._movieData.images){for(const[i,r]of Object.entries(this._movieData.images))if(r instanceof ImageBitmap)try{const o=await createImageBitmap(r);t[i]=o,s.push(o)}catch(o){console.warn("[\u79BB\u5C4F\u6E32\u67D3\u5668] \u91CD\u65B0\u53D1\u9001\u52A8\u753B\u6570\u636E\u65F6\u514B\u9686\u4F4D\u56FE\u5931\u8D25\uFF1A",o)}}const a={...this._movieData,images:t,imageBytes:void 0};x.set(this.id,e),this.worker.postMessage({type:d.SET_MOVIE,id:this.id,movieData:a,movieDataId:e},s)}}async setMovie(e){this._movieData=e;const t=e.movieDataId||"movie_direct_"+Math.random().toString(36).substring(2)+Date.now();x.set(this.id,t),this.worker.postMessage({type:d.SET_MOVIE,id:this.id,movieData:null,movieDataId:t})}async setImage(e,t){if(this._dynamicKeys.add(t),typeof createImageBitmap<"u")try{const s=await createImageBitmap(e);this.worker.postMessage({type:d.SET_IMAGE,id:this.id,key:t,image:s},[s])}catch(s){console.warn("[\u79BB\u5C4F\u6E32\u67D3\u5668] \u8BBE\u7F6E\u52A8\u6001\u56FE\u7247\u65F6\u514B\u9686\u4F4D\u56FE\u5BF9\u8C61\u5931\u8D25\uFF1A",s)}}setDynamicText(e,t){this._dynamicKeys.add(t),this.worker.postMessage({type:d.SET_DYNAMIC_TEXT,id:this.id,key:t,text:e})}setShapeRenderer(e){this._shapeRendererInstance=e}async drawExternalPoster(e){try{const t=await(await fetch(e)).blob(),s=await createImageBitmap(t);this.worker.postMessage({type:d.DRAW_EXTERNAL_POSTER,id:this.id,image:s},[s])}catch(t){console.warn("[\u79BB\u5C4F\u6E32\u67D3\u5668] \u8F7D\u5165\u5E76\u751F\u6210\u9759\u6001\u6D77\u62A5\u6D77\u62A5\u5931\u8D25\uFF1A",t)}}play(e){this.worker.postMessage({type:d.PLAY,id:this.id,config:e})}stop(){this.worker.postMessage({type:d.STOP,id:this.id})}pause(){this.worker.postMessage({type:d.PAUSE,id:this.id})}stepToFrame(e,t=!1){this.worker.postMessage({type:d.STEP_TO_FRAME,id:this.id,frame:e,andPlay:t})}stepToPercentage(e,t){this.worker.postMessage({type:d.STEP_TO_PERCENTAGE,id:this.id,percentage:e,andPlay:t})}clear(){this.worker.postMessage({type:d.CLEAR,id:this.id})}clearDynamicObject(e){this._dynamicKeys.delete(e),this.worker.postMessage({type:d.CLEAR_DYNAMIC_OBJECT,id:this.id,key:e})}clearDynamicObjects(){this._dynamicKeys.clear(),this.worker.postMessage({type:d.CLEAR_DYNAMIC_OBJECTS,id:this.id})}getMemoryInfo(){if(!this._movieData)return{fileSize:0,imageMemory:0,dictionaryMemory:0,version:"",fps:0,frames:0,width:0,height:0,dynamicKeys:[],desc:"\u672A\u52A0\u8F7D\u4EFB\u4F55\u52A8\u6548"};let e=0;this._movieData.images&&Object.values(this._movieData.images).forEach(c=>{c&&c.width&&(e+=c.width*c.height*4)});const t=JSON.stringify({params:this._movieData.params,sprites:this._movieData.sprites}).length,s=this._movieData.fileSize||0,a=this._movieData.version||"",i=this._movieData.params.fps||20,r=this._movieData.params.frames||0,o=this._movieData.params.viewBoxWidth||0,u=this._movieData.params.viewBoxHeight||0,h=Array.from(this._dynamicKeys);return{fileSize:s,imageMemory:e,dictionaryMemory:t,version:a,fps:i,frames:r,width:o,height:u,dynamicKeys:h,desc:`\u6E90\u6587\u4EF6\u5927\u5C0F: ${(s/1024).toFixed(2)} KB | \u9884\u4F30\u663E\u5B58(\u4F4D\u56FE\u4E0E\u7ED3\u6784): ${((e+t)/1024/1024).toFixed(2)} MB`}}destroy(){D&&D.unobserve(this.canvas),x.delete(this.id),R.delete(this.id),this.worker.postMessage({type:d.DESTROY,id:this.id})}}class N{static async loadUrl(e){const t=await fetch(e);if(!t.ok)throw new Error(`\u65E0\u6CD5\u4ECE ${e} \u52A0\u8F7D SVGA \u6587\u4EF6: ${t.statusText}`);return await t.arrayBuffer()}static async loadFile(e){return new Promise((t,s)=>{const a=new FileReader;a.onload=()=>{a.result instanceof ArrayBuffer?t(a.result):s(new Error("\u65E0\u6CD5\u8BFB\u53D6\u6587\u4EF6\u7684 ArrayBuffer \u6570\u636E"))},a.onerror=()=>s(a.error),a.readAsArrayBuffer(e)})}}let K=0;const M=new Map,f=new Map,$=20,S=new Map,p=new Map,T=new Map;function H(){if(f.size>$){const n=f.keys().next().value;n&&l.destroyCache(n)}}G(n=>{const{taskId:e,type:t,data:s,error:a}=n,i=M.get(e);if(i){const{useImageBitmap:r}=i;if(t===k.SUCCESS)if(s&&s.images&&!r){const o=[],u=s.images,h={};Object.keys(u).forEach(c=>{const m=u[c];if(m instanceof Uint8Array&&m.length>0){const y=new Promise(v=>{let E="image/png";m[0]===255&&m[1]===216?E="image/jpeg":m[0]===71&&m[1]===73&&m[2]===70?E="image/gif":m[0]===82&&m[1]===73&&m[2]===70&&m[3]===70&&(E="image/webp");const b=new Blob([m],{type:E}),P=URL.createObjectURL(b),A=new Image;A.onload=()=>{h[c]=A,URL.revokeObjectURL(P),v()},A.onerror=()=>{h[c]=A,URL.revokeObjectURL(P),v()},A.src=P});o.push(y)}else h[c]=m}),o.length>0?Promise.all(o).then(()=>{Object.keys(u).forEach(c=>{u[c]=null}),s.images=h,i.resolve(s)}).catch(c=>{i.reject(c)}):(s.images=h,i.resolve(s))}else i.resolve(s);else i.reject(new Error(a||"\u89E3\u6790 SVGA \u6587\u4EF6\u5931\u8D25"));M.delete(e)}});class l{static getCachedVideoItem(e){return f.get(e)}static async loadUrl(e,t){const s=t?.cache!==!1;if(s&&f.has(e)){const i=f.get(e);return f.delete(e),f.set(e,i),i}if(S.has(e))return S.get(e);const a=(async()=>{try{const i=await N.loadUrl(e),r=await l.parseBuffer(i,{...t,movieDataId:e});return s&&(f.set(e,r),H()),r}catch(i){throw S.delete(e),i}finally{S.delete(e)}})();return S.set(e,a),a}static async loadFile(e,t){const s=await N.loadFile(e);return await l.parseBuffer(s,t)}static parseBuffer(e,t){const s=t?.useImageBitmap??!1,a=t?.cache!==!1,i=t?.movieDataId||"movie_direct_"+Math.random().toString(36).substring(2)+Date.now();return new Promise((r,o)=>{try{const u=I(),h=++K;M.set(h,{resolve:r,reject:o,useImageBitmap:s}),u.postMessage({type:d.PARSE,taskId:h,buffer:e,fileSize:e.byteLength,movieDataId:i,useImageBitmap:s,cache:a},[e])}catch(u){u instanceof Error?o(u):o(new Error("\u672A\u77E5\u9519\u8BEF"))}})}static async load(e,t){const s=t?.cache!==!1;if(s&&p.has(e)){const i=p.get(e);return p.delete(e),p.set(e,i),i}if(T.has(e))return T.get(e);const a=(async()=>{try{const i=await N.loadUrl(e),r=await l.parseBufferOffscreen(i,e,t);if(s&&(p.set(e,r),p.size>$)){const o=p.keys().next().value;o&&l.destroyOffscreenCache(o)}return r}catch(i){throw T.delete(e),i}finally{T.delete(e)}})();return T.set(e,a),a}static parseBufferOffscreen(e,t,s){const a=s?.cache!==!1;return new Promise((i,r)=>{try{const o=I(),u=++K;M.set(u,{resolve:i,reject:r}),o.postMessage({type:d.PARSE_OFFSCREEN,taskId:u,buffer:e,fileSize:e.byteLength,movieDataId:t,cache:a},[e])}catch(o){o instanceof Error?r(o):r(new Error("\u672A\u77E5\u9519\u8BEF"))}})}static destroyCache(e){const t=f.get(e);t&&t.images&&Object.keys(t.images).forEach(s=>{const a=t.images[s];a&&(typeof a.close=="function"?a.close():a instanceof HTMLImageElement&&(a.src="")),t.images[s]=null}),f.delete(e)}static clearCache(){Array.from(f.keys()).forEach(e=>{l.destroyCache(e)}),f.clear()}static destroyOffscreenCache(e,t=!0){p.delete(e);try{I().postMessage({type:d.RELEASE_CACHE,movieDataId:e,force:t})}catch(s){console.warn("[Parser] \u53D1\u9001\u624B\u52A8\u9500\u6BC1\u6D88\u606F\u5931\u8D25\uFF1A",s)}}static clearOffscreenCache(){p.clear();try{I().postMessage({type:d.RELEASE_CACHE,movieDataId:void 0,force:!0})}catch(e){console.warn("[Parser] \u53D1\u9001\u6E05\u7A7A\u6240\u6709\u79BB\u5C4F\u7F13\u5B58\u6D88\u606F\u5931\u8D25\uFF1A",e)}}static destroy(e){if(e==null){l.clearCache(),l.clearOffscreenCache();return}if(typeof e=="string"){l.destroyCache(e),l.destroyOffscreenCache(e);return}if(typeof e=="object"){const{url:t,mainThread:s,offscreen:a}=e,i=s!==void 0?s:a===void 0,r=a!==void 0?a:s===void 0;t?(i&&l.destroyCache(t),r&&l.destroyOffscreenCache(t)):(i&&l.clearCache(),r&&l.clearOffscreenCache())}}static setWorkerConfig(e){Y(e)}}var q=Object.freeze({__proto__:null,Parser:l});const _=()=>typeof globalThis.requestAnimationFrame<"u"?globalThis.requestAnimationFrame.bind(globalThis):n=>setTimeout(()=>n(performance.now()),16.666666666666668),z=()=>typeof globalThis.cancelAnimationFrame<"u"?globalThis.cancelAnimationFrame.bind(globalThis):n=>clearTimeout(n);class B{static instance;sharedTasks=new Set;sharedRafId=0;standaloneTasks=new Map;static getInstance(){return B.instance||(B.instance=new B),B.instance}add(e,t=!0){if(t)this.sharedTasks.add(e),this.sharedTasks.size===1&&this.sharedRafId===0&&this.startShared();else if(!this.standaloneTasks.has(e)){const s=i=>{try{e(i)}catch(o){console.error("[SVGA \u5B9A\u65F6\u5668] \u72EC\u7ACB\u6E32\u67D3\u4EFB\u52A1\u6267\u884C\u5F02\u5E38\uFF1A",o)}const r=_()(s);this.standaloneTasks.set(e,r)},a=_()(s);this.standaloneTasks.set(e,a)}}remove(e){if(this.sharedTasks.has(e)&&(this.sharedTasks.delete(e),this.sharedTasks.size===0&&this.stopShared()),this.standaloneTasks.has(e)){const t=this.standaloneTasks.get(e);t&&z()(t),this.standaloneTasks.delete(e)}}startShared(){const e=t=>{this.sharedTasks.forEach(s=>{try{s(t)}catch(a){console.error("[SVGA \u5B9A\u65F6\u5668] \u5171\u4EAB\u6E32\u67D3\u4EFB\u52A1\u6267\u884C\u5F02\u5E38\uFF1A",a)}}),this.sharedTasks.size>0?this.sharedRafId=_()(e):this.sharedRafId=0};this.sharedRafId=_()(e)}stopShared(){this.sharedRafId!==0&&(z()(this.sharedRafId),this.sharedRafId=0)}}const U=B.getInstance(),j=new WeakMap;let O=null;class J{canvas;ctx;observerIsVisible=!0;movieData=null;isPlaying=!1;currentFrame=0;runtimeFps=20;totalFrames=0;shapeRendererInstance=null;lastTime=0;config;currentLoop=0;onStart;onPause;onStop;onLoopEnd;onProcess;dynamicElements={};startFrame=0;endFrame=0;frameCache=new Map;constructor(e,t){if(this.canvas=e,this.config=Object.assign({loop:0,useIntersectionObserver:!0,useSharedRAF:!0,useOffscreenCanvas:!1,invisibleBehavior:"pause"},t),this.ctx=e.getContext("2d"),!this.ctx)throw new Error("\u83B7\u53D6 2D \u4E0A\u4E0B\u6587\u5931\u8D25");j.set(e,this),this.initObserver()}initObserver(){typeof IntersectionObserver<"u"&&this.config.useIntersectionObserver!==!1&&(this.observerIsVisible=!0,O||(O=new IntersectionObserver(e=>{e.forEach(t=>{const s=j.get(t.target);s&&(s.observerIsVisible=t.isIntersecting)})})),O.observe(this.canvas))}setMovie(e){this.frameCache.clear(),this.movieData=e,this.totalFrames=e.params.frames||1,this.canvas.width=e.params.viewBoxWidth||300,this.canvas.height=e.params.viewBoxHeight||300,this.startFrame=Math.max(0,this.config.startFrame??0),this.endFrame=Math.min(this.totalFrames-1,this.config.endFrame??this.totalFrames-1),this.endFrame<this.startFrame&&(this.endFrame=this.startFrame),this.currentFrame=this.config.direction==="backward"?this.endFrame:this.startFrame,this.currentLoop=0}setImage(e,t){this.frameCache.clear(),this.dynamicElements[t]||(this.dynamicElements[t]={}),this.dynamicElements[t].image=e}setDynamicText(e,t){this.frameCache.clear(),this.dynamicElements[t]||(this.dynamicElements[t]={}),this.dynamicElements[t].text=e}clearDynamicObject(e){this.frameCache.clear(),this.dynamicElements[e]&&delete this.dynamicElements[e]}clearDynamicObjects(){this.frameCache.clear(),this.dynamicElements={}}async drawExternalPoster(e){return new Promise(t=>{const s=new Image;s.crossOrigin="anonymous",s.onload=()=>{if(this.isPlaying||this.movieData){t();return}const a=this.canvas.getBoundingClientRect();if(a.width>0&&a.height>0){const u=window.devicePixelRatio||1;this.canvas.width=a.width*u,this.canvas.height=a.height*u}else this.canvas.width=s.width,this.canvas.height=s.height;this.clearCanvas();const i=Math.min(this.canvas.width/s.width,this.canvas.height/s.height),r=s.width*i,o=s.height*i;this.ctx.drawImage(s,(this.canvas.width-r)/2,(this.canvas.height-o)/2,r,o),t()},s.onerror=()=>t(),s.src=e})}stepToFrame(e,t=!1){e<0||e>=this.totalFrames||(this.currentFrame=e,this.drawFrame(this.currentFrame),t?this.play():this.stop())}stepToPercentage(e,t=!1){const s=Math.floor(e*this.totalFrames);this.stepToFrame(s<this.totalFrames?s:this.totalFrames-1,t)}setShapeRenderer(e){this.shapeRendererInstance=e}getMemoryInfo(){if(!this.movieData)return{fileSize:0,imageMemory:0,dictionaryMemory:0,version:"",fps:0,frames:0,width:0,height:0,dynamicKeys:[],desc:"\u672A\u52A0\u8F7D\u4EFB\u4F55\u52A8\u6548"};let e=0;this.movieData.images&&Object.values(this.movieData.images).forEach(c=>{c&&typeof c=="object"&&"width"in c&&"height"in c&&(e+=c.width*c.height*4)});const t=JSON.stringify({params:this.movieData.params,sprites:this.movieData.sprites}).length,s=this.movieData.fileSize||0,a=this.movieData.version||"",i=this.movieData.params.fps||20,r=this.movieData.params.frames||0,o=this.movieData.params.viewBoxWidth||0,u=this.movieData.params.viewBoxHeight||0,h=Object.keys(this.dynamicElements);return{fileSize:s,imageMemory:e,dictionaryMemory:t,version:a,fps:i,frames:r,width:o,height:u,dynamicKeys:h,desc:`\u6E90\u6587\u4EF6\u5927\u5C0F: ${(s/1024).toFixed(2)} KB | \u9884\u4F30\u663E\u5B58(\u4F4D\u56FE\u4E0E\u7ED3\u6784): ${((e+t)/1024/1024).toFixed(2)} MB`}}play(e){!this.movieData||this.isPlaying||(e&&(e.fps!==void 0&&(this.config.fps=e.fps),e.loop!==void 0&&(this.config.loop=e.loop,this.currentLoop=0),e.fillMode!==void 0&&(this.config.fillMode=e.fillMode),e.startFrame!==void 0&&(this.config.startFrame=e.startFrame),e.endFrame!==void 0&&(this.config.endFrame=e.endFrame),e.useIntersectionObserver!==void 0&&(this.config.useIntersectionObserver=e.useIntersectionObserver),e.invisibleBehavior!==void 0&&(this.config.invisibleBehavior=e.invisibleBehavior),e.useSharedRAF!==void 0&&(this.config.useSharedRAF=e.useSharedRAF),e.cacheFrames!==void 0&&(this.config.cacheFrames!==e.cacheFrames&&this.frameCache.clear(),this.config.cacheFrames=e.cacheFrames),e.direction!==void 0&&(this.config.direction=e.direction)),this.startFrame=Math.max(0,this.config.startFrame??0),this.endFrame=Math.min(this.totalFrames-1,this.config.endFrame??this.totalFrames-1),this.endFrame<this.startFrame&&(this.endFrame=this.startFrame),(this.currentFrame<this.startFrame||this.currentFrame>this.endFrame)&&(this.currentFrame=this.config.direction==="backward"?this.endFrame:this.startFrame),this.runtimeFps=this.config.fps||this.movieData.params.fps||20,this.isPlaying=!0,this.onStart?.(),this.lastTime=performance.now(),U.add(this.loop,this.config.useSharedRAF!==!1))}stop(){this.isPlaying&&(this.isPlaying=!1,this.onStop?.()),U.remove(this.loop)}pause(){this.isPlaying&&(this.isPlaying=!1,this.onPause?.()),U.remove(this.loop)}reset(){this.stop(),this.currentFrame=0,this.currentLoop=0,this.clearCanvas(),this.movieData&&this.drawFrame(0)}clear(){this.stop(),this.clearCanvas(),this.frameCache.clear(),this.movieData=null,this.currentFrame=0,this.currentLoop=0}destroy(){this.clear(),this.clearDynamicObjects(),this.frameCache.clear(),O&&O.unobserve(this.canvas),j.delete(this.canvas),this.canvas=null,this.ctx=null,this.shapeRendererInstance=null}loop=e=>{if(!this.isPlaying)return;const t=1e3/this.runtimeFps,s=e-this.lastTime;if(s>=t){this.lastTime=e-s%t;const a=!this.observerIsVisible,i=this.config.invisibleBehavior==="pause"||!this.config.invisibleBehavior;if(a&&i)return;if(a||this.drawFrame(this.currentFrame),this.onProcess?.(this.currentFrame),this.config.direction!=="backward"){if(this.currentFrame++,this.currentFrame>this.endFrame||this.currentFrame>=this.totalFrames){if(this.currentLoop++,this.onLoopEnd?.(),this.config.loop&&this.config.loop>0&&this.currentLoop>=this.config.loop){this.stop(),this.config.fillMode==="backwards"?this.stepToFrame(this.startFrame):this.config.fillMode==="clear"?this.clearCanvas():this.drawFrame(this.endFrame);return}this.currentFrame=this.startFrame}}else if(this.currentFrame--,this.currentFrame<this.startFrame){if(this.currentLoop++,this.onLoopEnd?.(),this.config.loop&&this.config.loop>0&&this.currentLoop>=this.config.loop){this.stop(),this.config.fillMode==="backwards"?this.stepToFrame(this.endFrame):this.config.fillMode==="clear"?this.clearCanvas():this.drawFrame(this.startFrame);return}this.currentFrame=this.endFrame}}};clearCanvas(){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height)}drawFrame(e){if(!this.movieData)return;if(this.config.cacheFrames&&this.frameCache.has(e)){const a=this.frameCache.get(e);this.clearCanvas(),this.ctx.drawImage(a,0,0);return}this.clearCanvas();const{sprites:t,images:s}=this.movieData;for(const a of t){const i=a.frames?.[e];if(!i||i.alpha===0)continue;if(this.ctx.save(),this.ctx.globalAlpha=i.alpha,i.transform){const{a:u,b:h,c,d:m,tx:y,ty:v}=i.transform;this.ctx.transform(u,h,c,m,y,v)}if(i.clipPath){const u=new Path2D(i.clipPath);this.ctx.clip(u)}let r=null;if(a.imageKey){const u=this.dynamicElements[a.imageKey];u&&u.image?r=u.image:s&&s[a.imageKey]&&(r=s[a.imageKey])}const o=i.layout;if(r){let u=0,h=0;"width"in r&&(u=r.width),"height"in r&&(h=r.height),o?this.ctx.drawImage(r,o.x||0,o.y||0,Math.max(o.width,0)||u,Math.max(o.height,0)||h):this.ctx.drawImage(r,0,0)}if(a.imageKey&&this.dynamicElements[a.imageKey]&&this.dynamicElements[a.imageKey].text){const u=this.dynamicElements[a.imageKey].text,h=u.size||"14px",c=u.family||"Arial",m=u.color||"#000000",y=u.offset||{x:0,y:0},v=typeof h=="number"?`${h}px ${c}`:`${h} ${c}`;this.ctx.font=v,this.ctx.fillStyle=m,this.ctx.textBaseline="middle",this.ctx.textAlign="center";let E=y.x,b=y.y;o&&(E+=o.x+o.width/2,b+=o.y+o.height/2),this.ctx.fillText(u.text,E,b)}i.shapes&&i.shapes.length>0&&this.shapeRendererInstance&&this.shapeRendererInstance.drawShapes(this.ctx,i.shapes),this.ctx.restore()}if(this.config.cacheFrames){const a=document.createElement("canvas");a.width=this.canvas.width,a.height=this.canvas.height,a.getContext("2d")?.drawImage(this.canvas,0,0),this.frameCache.set(e,a)}}}class X{renderer;constructor(e,t){let s;e instanceof HTMLDivElement?(s=document.createElement("canvas"),s.style.width="100%",s.style.height="100%",e.appendChild(s)):s=e,t?.useOffscreenCanvas&&typeof s.transferControlToOffscreen=="function"&&typeof Worker<"u"?this.renderer=new V(s,t):this.renderer=new J(s,t)}async setVideoItem(e){this.renderer.clear();const t=this.renderer instanceof V;if(t){if(e&&typeof e=="object"&&!e.isOffscreen&&(e.sprites||e.images))throw new Error("[SVGA \u64AD\u653E\u5668\u4E25\u91CD\u9519\u8BEF] \u5F53\u524D\u5DF2\u5F00\u542F Offscreen \u79BB\u5C4F\u6E32\u67D3\u4F18\u5316\uFF01\u5728\u79BB\u5C4F\u6E32\u67D3\u6A21\u5F0F\u4E0B\uFF0C\u4E25\u683C\u7981\u6B62\u5411\u64AD\u653E\u5668 setVideoItem \u4F20\u9012\u4E3B\u7EBF\u7A0B\u7684\u5B8C\u6574\u590D\u6742 MovieData \u6570\u636E\uFF08\u8FD9\u4F1A\u5BFC\u81F4\u4E3B\u7EBF\u7A0B\u4E8C\u6B21\u53CD\u5E8F\u5217\u5316\u4E0E\u591A\u4EFD\u56FE\u50CF\u7559\u5B58\uFF0C\u4F7F\u624B\u673A\u5185\u5B58\u6210\u500D\u66B4\u589E\uFF09\u3002\u8BF7\u6539\u7528\u4E3A\u79BB\u5C4F\u6A21\u5F0F\u4E13\u5C5E\u89E3\u8026\u8BBE\u8BA1\u7684\u52A0\u8F7D\u65B9\u6CD5\u3010Parser.load(url)\u3011\u83B7\u53D6\u4EC5\u542B ID \u7684\u8F7B\u91CF\u53E5\u67C4\uFF0C\u6216\u8005\u76F4\u63A5\u4F20\u5165 String \u7C7B\u578B\u7684 URL \u81EA\u9002\u5E94\u79BB\u5C4F\u6D41\u3002")}else if(e&&typeof e=="object"&&e.isOffscreen)throw new Error("[SVGA \u64AD\u653E\u5668\u4E25\u91CD\u9519\u8BEF] \u5F53\u524D\u4F7F\u7528\u7684\u662F\u4E3B\u7EBF\u7A0B\u4F20\u7EDF\u6E32\u67D3\u5668\uFF0C\u4F46\u5374\u4F20\u5165\u4E86\u5B50\u7EBF\u7A0B\u4E13\u7528\u7684\u79BB\u5C4F\u8F7B\u91CF\u5316\u5143\u6570\u636E\u53E5\u67C4 (isOffscreen: true)\uFF01\u8FD9\u5C06\u5BFC\u81F4\u4E3B\u7EBF\u7A0B\u6CA1\u6709\u4EFB\u4F55\u53EF\u4EE5\u7528\u4E8E\u7ED8\u5236\u548C\u53CD\u5E8F\u5217\u5316\u7684\u56FE\u50CF/\u7CBE\u7075\u5E8F\u5217\u6811\u4FE1\u606F\u3002\u5728\u666E\u901A\u6E32\u67D3\u6A21\u5F0F\u4E0B\uFF0C\u8BF7\u4F7F\u7528\u4E3B\u7EBF\u7A0B\u52A0\u8F7D\u65B9\u6CD5\u3010Parser.loadUrl(url)\u3011\u6216\u3010Parser.loadFile(file)\u3011\u3002");if(typeof e=="string")if(t){await this.renderer.setMovie({movieDataId:e});return}else{const{Parser:a}=await Promise.resolve().then(function(){return q}),i=a.getCachedVideoItem(e)||await a.loadUrl(e);i&&await this.renderer.setMovie(i);return}let s=!1;if(e&&e.sprites)for(const a of e.sprites){if(s)break;if(a.frames){for(const i of a.frames)if(i.shapes&&i.shapes.length>0){s=!0;break}}}if(s){const{ShapeRenderer:a}=await Promise.resolve().then(function(){return require("./ShapeRenderer-Cuwcq2MV.cjs")});this.renderer.setShapeRenderer(a.getInstance())}await this.renderer.setMovie(e)}play(e){this.renderer.play(e)}playRange(e,t,s){this.renderer.play(Object.assign({startFrame:e,endFrame:t},s))}pause(){this.renderer.pause()}stop(){this.renderer.stop()}onStart(e){this.renderer.onStart=e}onPause(e){this.renderer.onPause=e}onStop(e){this.renderer.onStop=e}onLoopEnd(e){this.renderer.onLoopEnd=e}onProcess(e){this.renderer.onProcess=e}stepToFrame(e,t=!1){this.renderer.stepToFrame(e,t)}stepToPercentage(e,t=!1){this.renderer.stepToPercentage(e,t)}async setImage(e,t){if(typeof e=="string"){const s=new Image;s.crossOrigin="anonymous";const a=new Promise((i,r)=>{s.onload=()=>i(s),s.onerror=o=>r(o)});s.src=e;try{const i=await a;await this.renderer.setImage(i,t)}catch(i){console.warn(`[Player] \u52A8\u6001\u52A0\u8F7D\u56FE\u7247\u94FE\u63A5 ${e} \u5931\u8D25\uFF1A`,i)}}else await this.renderer.setImage(e,t)}setText(e,t){typeof e=="string"?this.renderer.setDynamicText({text:e},t):this.renderer.setDynamicText(e,t)}clearDynamicObject(e){this.renderer.clearDynamicObject(e)}clearDynamicObjects(){this.renderer.clearDynamicObjects()}async renderPoster(e){await this.renderer.drawExternalPoster(e)}getMemoryInfo(){return this.renderer.getMemoryInfo()}clear(){this.renderer.clear()}destroy(){this.renderer.destroy()}}exports.Parser=l,exports.Player=X;
1
+ "use strict";var f=typeof document<"u"?document.currentScript:null;const M=()=>typeof globalThis.requestAnimationFrame<"u"?globalThis.requestAnimationFrame.bind(globalThis):n=>setTimeout(()=>n(performance.now()),16.666666666666668),K=()=>typeof globalThis.cancelAnimationFrame<"u"?globalThis.cancelAnimationFrame.bind(globalThis):n=>clearTimeout(n);class S{static instance;sharedTasks=new Set;sharedRafId=0;standaloneTasks=new Map;static getInstance(){return S.instance||(S.instance=new S),S.instance}add(e,s=!0){if(s)this.sharedTasks.add(e),this.sharedTasks.size===1&&this.sharedRafId===0&&this.startShared();else if(!this.standaloneTasks.has(e)){const t=i=>{try{e(i)}catch(o){console.error("[SVGA \u5B9A\u65F6\u5668] \u72EC\u7ACB\u6E32\u67D3\u4EFB\u52A1\u6267\u884C\u5F02\u5E38\uFF1A",o)}const r=M()(t);this.standaloneTasks.set(e,r)},a=M()(t);this.standaloneTasks.set(e,a)}}remove(e){if(this.sharedTasks.has(e)&&(this.sharedTasks.delete(e),this.sharedTasks.size===0&&this.stopShared()),this.standaloneTasks.has(e)){const s=this.standaloneTasks.get(e);s&&K()(s),this.standaloneTasks.delete(e)}}startShared(){const e=s=>{this.sharedTasks.forEach(t=>{try{t(s)}catch(a){console.error("[SVGA \u5B9A\u65F6\u5668] \u5171\u4EAB\u6E32\u67D3\u4EFB\u52A1\u6267\u884C\u5F02\u5E38\uFF1A",a)}}),this.sharedTasks.size>0?this.sharedRafId=M()(e):this.sharedRafId=0};this.sharedRafId=M()(e)}stopShared(){this.sharedRafId!==0&&(K()(this.sharedRafId),this.sharedRafId=0)}}const L=S.getInstance(),U=new WeakMap;let T=null;class G{canvas;ctx;observerIsVisible=!0;movieData=null;isPlaying=!1;currentFrame=0;runtimeFps=20;totalFrames=0;shapeRendererInstance=null;lastTime=0;config;currentLoop=0;onStart;onPause;onStop;onLoopEnd;onProcess;dynamicElements={};startFrame=0;endFrame=0;frameCache=new Map;constructor(e,s){if(this.canvas=e,this.config=Object.assign({loop:0,useIntersectionObserver:!0,useSharedRAF:!0,useOffscreenCanvas:!1,invisibleBehavior:"pause"},s),this.ctx=e.getContext("2d"),!this.ctx)throw new Error("\u83B7\u53D6 2D \u4E0A\u4E0B\u6587\u5931\u8D25");U.set(e,this),this.initObserver()}initObserver(){typeof IntersectionObserver<"u"&&this.config.useIntersectionObserver!==!1&&(this.observerIsVisible=!0,T||(T=new IntersectionObserver(e=>{e.forEach(s=>{const t=U.get(s.target);t&&(t.observerIsVisible=s.isIntersecting)})})),T.observe(this.canvas))}setMovie(e){this.frameCache.clear(),this.movieData=e,this.totalFrames=e.params.frames||1,this.canvas.width=e.params.viewBoxWidth||300,this.canvas.height=e.params.viewBoxHeight||300,this.startFrame=Math.max(0,this.config.startFrame??0),this.endFrame=Math.min(this.totalFrames-1,this.config.endFrame??this.totalFrames-1),this.endFrame<this.startFrame&&(this.endFrame=this.startFrame),this.currentFrame=this.config.direction==="backward"?this.endFrame:this.startFrame,this.currentLoop=0}setImage(e,s){this.frameCache.clear(),this.dynamicElements[s]||(this.dynamicElements[s]={}),this.dynamicElements[s].image=e}setDynamicText(e,s){this.frameCache.clear(),this.dynamicElements[s]||(this.dynamicElements[s]={}),this.dynamicElements[s].text=e}clearDynamicObject(e){this.frameCache.clear(),this.dynamicElements[e]&&delete this.dynamicElements[e]}clearDynamicObjects(){this.frameCache.clear(),this.dynamicElements={}}async drawExternalPoster(e){return new Promise(s=>{const t=new Image;t.crossOrigin="anonymous",t.onload=()=>{if(this.isPlaying||this.movieData){s();return}const a=this.canvas.getBoundingClientRect();if(a.width>0&&a.height>0){const u=window.devicePixelRatio||1;this.canvas.width=a.width*u,this.canvas.height=a.height*u}else this.canvas.width=t.width,this.canvas.height=t.height;this.clearCanvas();const i=Math.min(this.canvas.width/t.width,this.canvas.height/t.height),r=t.width*i,o=t.height*i;this.ctx.drawImage(t,(this.canvas.width-r)/2,(this.canvas.height-o)/2,r,o),s()},t.onerror=()=>s(),t.src=e})}stepToFrame(e,s=!1){e<0||e>=this.totalFrames||(this.currentFrame=e,this.drawFrame(this.currentFrame),s?this.play():this.stop())}stepToPercentage(e,s=!1){const t=Math.floor(e*this.totalFrames);this.stepToFrame(t<this.totalFrames?t:this.totalFrames-1,s)}setShapeRenderer(e){this.shapeRendererInstance=e}getMemoryInfo(){if(!this.movieData)return{fileSize:0,imageMemory:0,dictionaryMemory:0,version:"",fps:0,frames:0,width:0,height:0,dynamicKeys:[],desc:"\u672A\u52A0\u8F7D\u4EFB\u4F55\u52A8\u6548"};let e=0;this.movieData.images&&Object.values(this.movieData.images).forEach(c=>{c&&typeof c=="object"&&"width"in c&&"height"in c&&(e+=c.width*c.height*4)});const s=JSON.stringify({params:this.movieData.params,sprites:this.movieData.sprites}).length,t=this.movieData.fileSize||0,a=this.movieData.version||"",i=this.movieData.params.fps||20,r=this.movieData.params.frames||0,o=this.movieData.params.viewBoxWidth||0,u=this.movieData.params.viewBoxHeight||0,h=Object.keys(this.dynamicElements);return{fileSize:t,imageMemory:e,dictionaryMemory:s,version:a,fps:i,frames:r,width:o,height:u,dynamicKeys:h,desc:`\u6E90\u6587\u4EF6\u5927\u5C0F: ${(t/1024).toFixed(2)} KB | \u9884\u4F30\u663E\u5B58(\u4F4D\u56FE\u4E0E\u7ED3\u6784): ${((e+s)/1024/1024).toFixed(2)} MB`}}play(e){!this.movieData||this.isPlaying||(e&&(e.fps!==void 0&&(this.config.fps=e.fps),e.loop!==void 0&&(this.config.loop=e.loop,this.currentLoop=0),e.fillMode!==void 0&&(this.config.fillMode=e.fillMode),e.startFrame!==void 0&&(this.config.startFrame=e.startFrame),e.endFrame!==void 0&&(this.config.endFrame=e.endFrame),e.useIntersectionObserver!==void 0&&(this.config.useIntersectionObserver=e.useIntersectionObserver),e.invisibleBehavior!==void 0&&(this.config.invisibleBehavior=e.invisibleBehavior),e.useSharedRAF!==void 0&&(this.config.useSharedRAF=e.useSharedRAF),e.cacheFrames!==void 0&&(this.config.cacheFrames!==e.cacheFrames&&this.frameCache.clear(),this.config.cacheFrames=e.cacheFrames),e.direction!==void 0&&(this.config.direction=e.direction)),this.startFrame=Math.max(0,this.config.startFrame??0),this.endFrame=Math.min(this.totalFrames-1,this.config.endFrame??this.totalFrames-1),this.endFrame<this.startFrame&&(this.endFrame=this.startFrame),(this.currentFrame<this.startFrame||this.currentFrame>this.endFrame)&&(this.currentFrame=this.config.direction==="backward"?this.endFrame:this.startFrame),this.runtimeFps=this.config.fps||this.movieData.params.fps||20,this.isPlaying=!0,this.onStart?.(),this.lastTime=performance.now(),L.add(this.loop,this.config.useSharedRAF!==!1))}stop(){this.isPlaying&&(this.isPlaying=!1,this.onStop?.()),L.remove(this.loop)}pause(){this.isPlaying&&(this.isPlaying=!1,this.onPause?.()),L.remove(this.loop)}reset(){this.stop(),this.currentFrame=0,this.currentLoop=0,this.clearCanvas(),this.movieData&&this.drawFrame(0)}clear(){this.stop(),this.clearCanvas(),this.frameCache.clear(),this.movieData=null,this.currentFrame=0,this.currentLoop=0}destroy(){this.clear(),this.clearDynamicObjects(),this.frameCache.clear(),T&&T.unobserve(this.canvas),U.delete(this.canvas),this.canvas=null,this.ctx=null,this.shapeRendererInstance=null}loop=e=>{if(!this.isPlaying)return;const s=1e3/this.runtimeFps,t=e-this.lastTime;if(t>=s){this.lastTime=e-t%s;const a=!this.observerIsVisible,i=this.config.invisibleBehavior==="pause"||!this.config.invisibleBehavior;if(a&&i)return;if(a||this.drawFrame(this.currentFrame),this.onProcess?.(this.currentFrame),this.config.direction!=="backward"){if(this.currentFrame++,this.currentFrame>this.endFrame||this.currentFrame>=this.totalFrames){if(this.currentLoop++,this.onLoopEnd?.(),this.config.loop&&this.config.loop>0&&this.currentLoop>=this.config.loop){this.stop(),this.config.fillMode==="backwards"?this.stepToFrame(this.startFrame):this.config.fillMode==="clear"?this.clearCanvas():this.drawFrame(this.endFrame);return}this.currentFrame=this.startFrame}}else if(this.currentFrame--,this.currentFrame<this.startFrame){if(this.currentLoop++,this.onLoopEnd?.(),this.config.loop&&this.config.loop>0&&this.currentLoop>=this.config.loop){this.stop(),this.config.fillMode==="backwards"?this.stepToFrame(this.endFrame):this.config.fillMode==="clear"?this.clearCanvas():this.drawFrame(this.startFrame);return}this.currentFrame=this.endFrame}}};clearCanvas(){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height)}drawFrame(e){if(!this.movieData)return;if(this.config.cacheFrames&&this.frameCache.has(e)){const a=this.frameCache.get(e);this.clearCanvas(),this.ctx.drawImage(a,0,0);return}this.clearCanvas();const{sprites:s,images:t}=this.movieData;for(const a of s){const i=a.frames?.[e];if(!i||i.alpha===0)continue;if(this.ctx.save(),this.ctx.globalAlpha=i.alpha,i.transform){const{a:u,b:h,c,d,tx:v,ty:w}=i.transform;this.ctx.transform(u,h,c,d,v,w)}if(i.clipPath){const u=new Path2D(i.clipPath);this.ctx.clip(u)}let r=null;if(a.imageKey){const u=this.dynamicElements[a.imageKey];u&&u.image?r=u.image:t&&t[a.imageKey]&&(r=t[a.imageKey])}const o=i.layout;if(r){let u=0,h=0;"width"in r&&(u=r.width),"height"in r&&(h=r.height),o?this.ctx.drawImage(r,o.x||0,o.y||0,Math.max(o.width,0)||u,Math.max(o.height,0)||h):this.ctx.drawImage(r,0,0)}if(a.imageKey&&this.dynamicElements[a.imageKey]&&this.dynamicElements[a.imageKey].text){const u=this.dynamicElements[a.imageKey].text,h=u.size||"14px",c=u.family||"Arial",d=u.color||"#000000",v=u.offset||{x:0,y:0},w=typeof h=="number"?`${h}px ${c}`:`${h} ${c}`;this.ctx.font=w,this.ctx.fillStyle=d,this.ctx.textBaseline="middle",this.ctx.textAlign="center";let E=v.x,B=v.y;o&&(E+=o.x+o.width/2,B+=o.y+o.height/2),this.ctx.fillText(u.text,E,B)}i.shapes&&i.shapes.length>0&&this.shapeRendererInstance&&this.shapeRendererInstance.drawShapes(this.ctx,i.shapes),this.ctx.restore()}if(this.config.cacheFrames){const a=document.createElement("canvas");a.width=this.canvas.width,a.height=this.canvas.height,a.getContext("2d")?.drawImage(this.canvas,0,0),this.frameCache.set(e,a)}}}var l=(n=>(n.INIT="init",n.VISIBILITY="visibility",n.SET_MOVIE="setMovie",n.SET_IMAGE="setImage",n.SET_DYNAMIC_TEXT="setDynamicText",n.DRAW_EXTERNAL_POSTER="drawExternalPoster",n.PLAY="play",n.STOP="stop",n.PAUSE="pause",n.STEP_TO_FRAME="stepToFrame",n.STEP_TO_PERCENTAGE="stepToPercentage",n.CLEAR="clear",n.CLEAR_DYNAMIC_OBJECTS="clearDynamicObjects",n.CLEAR_DYNAMIC_OBJECT="clearDynamicObject",n.DESTROY="destroy",n.PARSE="parse",n.PARSE_OFFSCREEN="parse_offscreen",n.RELEASE_CACHE="releaseCache",n))(l||{}),P=(n=>(n.SUCCESS="SUCCESS",n.ERROR="ERROR",n.EVENT="event",n))(P||{}),D=(n=>(n.READY="ready",n.ON_START="onStart",n.ON_STOP="onStop",n.ON_PAUSE="onPause",n.ON_PROCESS="onProcess",n.ON_LOOP_END="onLoopEnd",n.ON_REQUEST_MOVIE_DATA="onRequestMovieData",n))(D||{});let g=null,A=null;const k=new Map;let H=0,F={};function W(n){F={...F,...n}}const N=new Map;let j=null;function J(n){j=n}function b(){if(!g){if(F.workerInstance)g=F.workerInstance;else if(F.workerCreator)g=F.workerCreator();else if(F.workerString){const n=new Blob([F.workerString],{type:"application/javascript"}),e=URL.createObjectURL(n);g=new Worker(e)}else if(F.workerUrl){const n=F.workerUrl;if(!n.startsWith(window.location.origin)&&/^(https?:)?\/\//.test(n)){const e=`importScripts(${JSON.stringify(n)});`,s=new Blob([e],{type:"application/javascript"}),t=URL.createObjectURL(s);g=new Worker(t)}else g=new Worker(n)}else{let n;try{if(typeof{url:typeof document>"u"?require("url").pathToFileURL(__filename).href:f&&f.tagName.toUpperCase()==="SCRIPT"&&f.src||new URL("index.cjs",document.baseURI).href}<"u"&&(typeof document>"u"?require("url").pathToFileURL(__filename).href:f&&f.tagName.toUpperCase()==="SCRIPT"&&f.src||new URL("index.cjs",document.baseURI).href)){const e=typeof{url:typeof document>"u"?require("url").pathToFileURL(__filename).href:f&&f.tagName.toUpperCase()==="SCRIPT"&&f.src||new URL("index.cjs",document.baseURI).href}<"u"&&void 0,s=typeof globalThis<"u"?globalThis.process:void 0;(e?(void 0).DEV:typeof s<"u"&&s.env&&s.env.NODE_ENV!=="production")?n=new URL("./svga.worker.ts",typeof document>"u"?require("url").pathToFileURL(__filename).href:f&&f.tagName.toUpperCase()==="SCRIPT"&&f.src||new URL("index.cjs",document.baseURI).href):n=new URL("./svga.worker.js",typeof document>"u"?require("url").pathToFileURL(__filename).href:f&&f.tagName.toUpperCase()==="SCRIPT"&&f.src||new URL("index.cjs",document.baseURI).href)}else n="./svga.worker.js"}catch{n="./svga.worker.js"}g=new Worker(n,{type:"module"})}g.onmessage=n=>{const{type:e,id:s,name:t,args:a,taskId:i}=n.data;if(i!==void 0){j&&j(n.data);return}const r=k.get(s);r&&e===P.EVENT&&(t===D.ON_START&&r.onStart?r.onStart():t===D.ON_STOP&&r.onStop?r.onStop():t===D.ON_PAUSE&&r.onPause?r.onPause():t===D.ON_LOOP_END&&r.onLoopEnd?r.onLoopEnd():t===D.ON_PROCESS&&r.onProcess?r.onProcess(a[0]):t===D.ON_REQUEST_MOVIE_DATA&&r.resendMovieData())}}return g}class ${id;canvas;observerIsVisible=!0;worker;onStart;onPause;onStop;onLoopEnd;onProcess;_dynamicKeys=new Set;_config;_shapeRendererInstance=null;_movieData=null;constructor(e,s){this.canvas=e,this.id=`renderer_${H++}`,this._config=Object.assign({loop:0,useIntersectionObserver:!0,useSharedRAF:!0,invisibleBehavior:"pause"},s),k.set(this.id,this),this.worker=b();const t=e.transferControlToOffscreen();this.worker.postMessage({type:l.INIT,id:this.id,canvas:t,config:this._config},[t]),this._config.useIntersectionObserver!==!1&&(!A&&typeof IntersectionObserver<"u"&&(A=new IntersectionObserver(a=>{a.forEach(i=>{Array.from(k.values()).filter(r=>r.canvas===i.target).forEach(r=>{r.observerIsVisible=i.isIntersecting,r.worker.postMessage({type:l.VISIBILITY,id:r.id,visible:r.observerIsVisible})})})})),A&&A.observe(this.canvas))}async resendMovieData(){if(this._movieData){const e=this._movieData.movieDataId||"movie_direct_"+Math.random().toString(36).substring(2)+Date.now(),s={},t=[];if(typeof createImageBitmap<"u"&&this._movieData.images){for(const[i,r]of Object.entries(this._movieData.images))if(r instanceof ImageBitmap)try{const o=await createImageBitmap(r);s[i]=o,t.push(o)}catch(o){console.warn("[\u79BB\u5C4F\u6E32\u67D3\u5668] \u91CD\u65B0\u53D1\u9001\u52A8\u753B\u6570\u636E\u65F6\u514B\u9686\u4F4D\u56FE\u5931\u8D25\uFF1A",o)}}const a={...this._movieData,images:s,imageBytes:void 0};N.set(this.id,e),this.worker.postMessage({type:l.SET_MOVIE,id:this.id,movieData:a,movieDataId:e},t)}}async setMovie(e){this._movieData=e;const s=e.movieDataId||"movie_direct_"+Math.random().toString(36).substring(2)+Date.now();N.set(this.id,s),this.worker.postMessage({type:l.SET_MOVIE,id:this.id,movieData:null,movieDataId:s})}async setImage(e,s){if(this._dynamicKeys.add(s),typeof createImageBitmap<"u")try{const t=await createImageBitmap(e);this.worker.postMessage({type:l.SET_IMAGE,id:this.id,key:s,image:t},[t])}catch(t){console.warn("[\u79BB\u5C4F\u6E32\u67D3\u5668] \u8BBE\u7F6E\u52A8\u6001\u56FE\u7247\u65F6\u514B\u9686\u4F4D\u56FE\u5BF9\u8C61\u5931\u8D25\uFF1A",t)}}setDynamicText(e,s){this._dynamicKeys.add(s),this.worker.postMessage({type:l.SET_DYNAMIC_TEXT,id:this.id,key:s,text:e})}setShapeRenderer(e){this._shapeRendererInstance=e}async drawExternalPoster(e){try{const s=await(await fetch(e)).blob(),t=await createImageBitmap(s);this.worker.postMessage({type:l.DRAW_EXTERNAL_POSTER,id:this.id,image:t},[t])}catch(s){console.warn("[\u79BB\u5C4F\u6E32\u67D3\u5668] \u8F7D\u5165\u5E76\u751F\u6210\u9759\u6001\u6D77\u62A5\u6D77\u62A5\u5931\u8D25\uFF1A",s)}}play(e){this.worker.postMessage({type:l.PLAY,id:this.id,config:e})}stop(){this.worker.postMessage({type:l.STOP,id:this.id})}pause(){this.worker.postMessage({type:l.PAUSE,id:this.id})}stepToFrame(e,s=!1){this.worker.postMessage({type:l.STEP_TO_FRAME,id:this.id,frame:e,andPlay:s})}stepToPercentage(e,s){this.worker.postMessage({type:l.STEP_TO_PERCENTAGE,id:this.id,percentage:e,andPlay:s})}clear(){this.worker.postMessage({type:l.CLEAR,id:this.id})}clearDynamicObject(e){this._dynamicKeys.delete(e),this.worker.postMessage({type:l.CLEAR_DYNAMIC_OBJECT,id:this.id,key:e})}clearDynamicObjects(){this._dynamicKeys.clear(),this.worker.postMessage({type:l.CLEAR_DYNAMIC_OBJECTS,id:this.id})}getMemoryInfo(){if(!this._movieData)return{fileSize:0,imageMemory:0,dictionaryMemory:0,version:"",fps:0,frames:0,width:0,height:0,dynamicKeys:[],desc:"\u672A\u52A0\u8F7D\u4EFB\u4F55\u52A8\u6548"};let e=0;this._movieData.images&&Object.values(this._movieData.images).forEach(c=>{c&&c.width&&(e+=c.width*c.height*4)});const s=JSON.stringify({params:this._movieData.params,sprites:this._movieData.sprites}).length,t=this._movieData.fileSize||0,a=this._movieData.version||"",i=this._movieData.params.fps||20,r=this._movieData.params.frames||0,o=this._movieData.params.viewBoxWidth||0,u=this._movieData.params.viewBoxHeight||0,h=Array.from(this._dynamicKeys);return{fileSize:t,imageMemory:e,dictionaryMemory:s,version:a,fps:i,frames:r,width:o,height:u,dynamicKeys:h,desc:`\u6E90\u6587\u4EF6\u5927\u5C0F: ${(t/1024).toFixed(2)} KB | \u9884\u4F30\u663E\u5B58(\u4F4D\u56FE\u4E0E\u7ED3\u6784): ${((e+s)/1024/1024).toFixed(2)} MB`}}destroy(){A&&A.unobserve(this.canvas),N.delete(this.id),k.delete(this.id),this.worker.postMessage({type:l.DESTROY,id:this.id})}}class q{renderer;constructor(e,s){let t;e instanceof HTMLDivElement?(t=document.createElement("canvas"),t.style.width="100%",t.style.height="100%",e.appendChild(t)):t=e,s?.useOffscreenCanvas&&typeof t.transferControlToOffscreen=="function"&&typeof Worker<"u"?this.renderer=new $(t,s):this.renderer=new G(t,s)}async setVideoItem(e){this.renderer.clear();const s=this.renderer instanceof $;if(s){if(e&&typeof e=="object"&&!e.isOffscreen&&(e.sprites||e.images))throw new Error("[SVGA \u64AD\u653E\u5668\u4E25\u91CD\u9519\u8BEF] \u5F53\u524D\u5DF2\u5F00\u542F Offscreen \u79BB\u5C4F\u6E32\u67D3\u4F18\u5316\uFF01\u5728\u79BB\u5C4F\u6E32\u67D3\u6A21\u5F0F\u4E0B\uFF0C\u4E25\u683C\u7981\u6B62\u5411\u64AD\u653E\u5668 setVideoItem \u4F20\u9012\u4E3B\u7EBF\u7A0B\u7684\u5B8C\u6574\u590D\u6742 MovieData \u6570\u636E\uFF08\u8FD9\u4F1A\u5BFC\u81F4\u4E3B\u7EBF\u7A0B\u4E8C\u6B21\u53CD\u5E8F\u5217\u5316\u4E0E\u591A\u4EFD\u56FE\u50CF\u7559\u5B58\uFF0C\u4F7F\u624B\u673A\u5185\u5B58\u6210\u500D\u66B4\u589E\uFF09\u3002\u8BF7\u6539\u7528\u4E3A\u79BB\u5C4F\u6A21\u5F0F\u4E13\u5C5E\u89E3\u8026\u8BBE\u8BA1\u7684\u52A0\u8F7D\u65B9\u6CD5\u3010Parser.load(url)\u3011\u83B7\u53D6\u4EC5\u542B ID \u7684\u8F7B\u91CF\u53E5\u67C4\uFF0C\u6216\u8005\u76F4\u63A5\u4F20\u5165 String \u7C7B\u578B\u7684 URL \u81EA\u9002\u5E94\u79BB\u5C4F\u6D41\u3002")}else if(e&&typeof e=="object"&&e.isOffscreen)throw new Error("[SVGA \u64AD\u653E\u5668\u4E25\u91CD\u9519\u8BEF] \u5F53\u524D\u4F7F\u7528\u7684\u662F\u4E3B\u7EBF\u7A0B\u4F20\u7EDF\u6E32\u67D3\u5668\uFF0C\u4F46\u5374\u4F20\u5165\u4E86\u5B50\u7EBF\u7A0B\u4E13\u7528\u7684\u79BB\u5C4F\u8F7B\u91CF\u5316\u5143\u6570\u636E\u53E5\u67C4 (isOffscreen: true)\uFF01\u8FD9\u5C06\u5BFC\u81F4\u4E3B\u7EBF\u7A0B\u6CA1\u6709\u4EFB\u4F55\u53EF\u4EE5\u7528\u4E8E\u7ED8\u5236\u548C\u53CD\u5E8F\u5217\u5316\u7684\u56FE\u50CF/\u7CBE\u7075\u5E8F\u5217\u6811\u4FE1\u606F\u3002\u5728\u666E\u901A\u6E32\u67D3\u6A21\u5F0F\u4E0B\uFF0C\u8BF7\u4F7F\u7528\u4E3B\u7EBF\u7A0B\u52A0\u8F7D\u65B9\u6CD5\u3010Parser.loadUrl(url)\u3011\u6216\u3010Parser.loadFile(file)\u3011\u3002");if(typeof e=="string")if(s){await this.renderer.setMovie({movieDataId:e});return}else{const{Parser:a}=await Promise.resolve().then(function(){return Q}),i=a.getCachedVideoItem(e)||await a.loadUrl(e);i&&await this.renderer.setMovie(i);return}let t=!1;if(e&&e.sprites)for(const a of e.sprites){if(t)break;if(a.frames){for(const i of a.frames)if(i.shapes&&i.shapes.length>0){t=!0;break}}}if(t){const{ShapeRenderer:a}=await Promise.resolve().then(function(){return Z});this.renderer.setShapeRenderer(a.getInstance())}await this.renderer.setMovie(e)}play(e){this.renderer.play(e)}playRange(e,s,t){this.renderer.play(Object.assign({startFrame:e,endFrame:s},t))}pause(){this.renderer.pause()}stop(){this.renderer.stop()}onStart(e){this.renderer.onStart=e}onPause(e){this.renderer.onPause=e}onStop(e){this.renderer.onStop=e}onLoopEnd(e){this.renderer.onLoopEnd=e}onProcess(e){this.renderer.onProcess=e}stepToFrame(e,s=!1){this.renderer.stepToFrame(e,s)}stepToPercentage(e,s=!1){this.renderer.stepToPercentage(e,s)}async setImage(e,s){if(typeof e=="string"){const t=new Image;t.crossOrigin="anonymous";const a=new Promise((i,r)=>{t.onload=()=>i(t),t.onerror=o=>r(o)});t.src=e;try{const i=await a;await this.renderer.setImage(i,s)}catch(i){console.warn(`[Player] \u52A8\u6001\u52A0\u8F7D\u56FE\u7247\u94FE\u63A5 ${e} \u5931\u8D25\uFF1A`,i)}}else await this.renderer.setImage(e,s)}setText(e,s){typeof e=="string"?this.renderer.setDynamicText({text:e},s):this.renderer.setDynamicText(e,s)}clearDynamicObject(e){this.renderer.clearDynamicObject(e)}clearDynamicObjects(){this.renderer.clearDynamicObjects()}async renderPoster(e){await this.renderer.drawExternalPoster(e)}getMemoryInfo(){return this.renderer.getMemoryInfo()}clear(){this.renderer.clear()}destroy(){this.renderer.destroy()}}class V{static async loadUrl(e){const s=await fetch(e);if(!s.ok)throw new Error(`\u65E0\u6CD5\u4ECE ${e} \u52A0\u8F7D SVGA \u6587\u4EF6: ${s.statusText}`);return await s.arrayBuffer()}static async loadFile(e){return new Promise((s,t)=>{const a=new FileReader;a.onload=()=>{a.result instanceof ArrayBuffer?s(a.result):t(new Error("\u65E0\u6CD5\u8BFB\u53D6\u6587\u4EF6\u7684 ArrayBuffer \u6570\u636E"))},a.onerror=()=>t(a.error),a.readAsArrayBuffer(e)})}}let z=0;const x=new Map,p=new Map,Y=20,O=new Map,y=new Map,_=new Map;function X(){if(p.size>Y){const n=p.keys().next().value;n&&m.destroyCache(n)}}J(n=>{const{taskId:e,type:s,data:t,error:a}=n,i=x.get(e);if(i){const{useImageBitmap:r}=i;if(s===P.SUCCESS)if(t&&t.images&&!r){const o=[],u=t.images,h={};Object.keys(u).forEach(c=>{const d=u[c];if(d instanceof Uint8Array&&d.length>0){const v=new Promise(w=>{let E="image/png";d[0]===255&&d[1]===216?E="image/jpeg":d[0]===71&&d[1]===73&&d[2]===70?E="image/gif":d[0]===82&&d[1]===73&&d[2]===70&&d[3]===70&&(E="image/webp");const B=new Blob([d],{type:E}),R=URL.createObjectURL(B),C=new Image;C.onload=()=>{h[c]=C,URL.revokeObjectURL(R),w()},C.onerror=()=>{h[c]=C,URL.revokeObjectURL(R),w()},C.src=R});o.push(v)}else h[c]=d}),o.length>0?Promise.all(o).then(()=>{Object.keys(u).forEach(c=>{u[c]=null}),t.images=h,i.resolve(t)}).catch(c=>{i.reject(c)}):(t.images=h,i.resolve(t))}else i.resolve(t);else i.reject(new Error(a||"\u89E3\u6790 SVGA \u6587\u4EF6\u5931\u8D25"));x.delete(e)}});class m{static getCachedVideoItem(e){return p.get(e)}static async loadUrl(e,s){const t=s?.cache!==!1;if(t&&p.has(e)){const i=p.get(e);return p.delete(e),p.set(e,i),i}if(O.has(e))return O.get(e);const a=(async()=>{try{const i=await V.loadUrl(e),r=await m.parseBuffer(i,{...s,movieDataId:e});return t&&(p.set(e,r),X()),r}catch(i){throw O.delete(e),i}finally{O.delete(e)}})();return O.set(e,a),a}static async loadFile(e,s){const t=await V.loadFile(e);return await m.parseBuffer(t,s)}static parseBuffer(e,s){const t=s?.useImageBitmap??!1,a=s?.cache!==!1,i=s?.movieDataId||"movie_direct_"+Math.random().toString(36).substring(2)+Date.now();return new Promise((r,o)=>{try{const u=b(),h=++z;x.set(h,{resolve:r,reject:o,useImageBitmap:t}),u.postMessage({type:l.PARSE,taskId:h,buffer:e,fileSize:e.byteLength,movieDataId:i,useImageBitmap:t,cache:a},[e])}catch(u){u instanceof Error?o(u):o(new Error("\u672A\u77E5\u9519\u8BEF"))}})}static async load(e,s){const t=s?.cache!==!1;if(t&&y.has(e)){const i=y.get(e);return y.delete(e),y.set(e,i),i}if(_.has(e))return _.get(e);const a=(async()=>{try{const i=await V.loadUrl(e),r=await m.parseBufferOffscreen(i,e,s);if(t&&(y.set(e,r),y.size>Y)){const o=y.keys().next().value;o&&m.destroyOffscreenCache(o)}return r}catch(i){throw _.delete(e),i}finally{_.delete(e)}})();return _.set(e,a),a}static parseBufferOffscreen(e,s,t){const a=t?.cache!==!1;return new Promise((i,r)=>{try{const o=b(),u=++z;x.set(u,{resolve:i,reject:r}),o.postMessage({type:l.PARSE_OFFSCREEN,taskId:u,buffer:e,fileSize:e.byteLength,movieDataId:s,cache:a},[e])}catch(o){o instanceof Error?r(o):r(new Error("\u672A\u77E5\u9519\u8BEF"))}})}static destroyCache(e){const s=p.get(e);s&&s.images&&Object.keys(s.images).forEach(t=>{const a=s.images[t];a&&(typeof a.close=="function"?a.close():a instanceof HTMLImageElement&&(a.src="")),s.images[t]=null}),p.delete(e)}static clearCache(){Array.from(p.keys()).forEach(e=>{m.destroyCache(e)}),p.clear()}static destroyOffscreenCache(e,s=!0){y.delete(e);try{b().postMessage({type:l.RELEASE_CACHE,movieDataId:e,force:s})}catch(t){console.warn("[Parser] \u53D1\u9001\u624B\u52A8\u9500\u6BC1\u6D88\u606F\u5931\u8D25\uFF1A",t)}}static clearOffscreenCache(){y.clear();try{b().postMessage({type:l.RELEASE_CACHE,movieDataId:void 0,force:!0})}catch(e){console.warn("[Parser] \u53D1\u9001\u6E05\u7A7A\u6240\u6709\u79BB\u5C4F\u7F13\u5B58\u6D88\u606F\u5931\u8D25\uFF1A",e)}}static destroy(e){if(e==null){m.clearCache(),m.clearOffscreenCache();return}if(typeof e=="string"){m.destroyCache(e),m.destroyOffscreenCache(e);return}if(typeof e=="object"){const{url:s,mainThread:t,offscreen:a}=e,i=t!==void 0?t:a===void 0,r=a!==void 0?a:t===void 0;s?(i&&m.destroyCache(s),r&&m.destroyOffscreenCache(s)):(i&&m.clearCache(),r&&m.clearOffscreenCache())}}static setWorkerConfig(e){W(e)}}var Q=Object.freeze({__proto__:null,Parser:m});class I{static instance;constructor(){}static getInstance(){return I.instance||(I.instance=new I),I.instance}drawShapes(e,s){for(const t of s){let a=null;if(t.type===0&&t.shape&&t.shape.d)a=new Path2D(t.shape.d);else if(t.type===1&&t.rect){const{x:i,y:r,width:o,height:u,cornerRadius:h}=t.rect;a=new Path2D,h>0?a.roundRect(i,r,o,u,h):a.rect(i,r,o,u)}else if(t.type===2&&t.ellipse){const{x:i,y:r,radiusX:o,radiusY:u}=t.ellipse;a=new Path2D,a.ellipse(i,r,o,u,0,0,2*Math.PI)}if(a&&t.styles){const{fill:i,stroke:r,strokeWidth:o,lineCap:u,lineJoin:h,miterLimit:c,lineDash:d}=t.styles;if(t.transform){e.save();const{a:v,b:w,c:E,d:B,tx:R,ty:C}=t.transform;e.transform(v,w,E,B,R,C)}i&&(e.fillStyle="rgba("+i.r*255+", "+i.g*255+", "+i.b*255+", "+i.a+")",e.fill(a)),r&&(e.strokeStyle="rgba("+r.r*255+", "+r.g*255+", "+r.b*255+", "+r.a+")",e.lineWidth=o||1,u&&(e.lineCap=u.toLowerCase()),h&&(e.lineJoin=h.toLowerCase()),c&&(e.miterLimit=c),d&&d.length>0?e.setLineDash(d):e.setLineDash([]),e.stroke(a)),t.transform&&e.restore()}}}}var Z=Object.freeze({__proto__:null,ShapeRenderer:I});exports.Parser=m,exports.Player=q,exports.SVGA_EVENT_NAME=D,exports.WORKER_ACTION=l,exports.WORKER_RESPONSE_TYPE=P,exports.setWorkerConfig=W;
package/dist/index.d.ts CHANGED
@@ -95,6 +95,36 @@ interface PlayConfig {
95
95
  */
96
96
  direction?: 'forward' | 'backward';
97
97
  }
98
+ /**
99
+ * 解析后的 SVGA 数据结构实体(可选部分属性用于类型推断)
100
+ */
101
+ interface MovieData {
102
+ /** 动效全局参数 */
103
+ params: {
104
+ /** 视图宽度 */
105
+ viewBoxWidth: number;
106
+ /** 视图高度 */
107
+ viewBoxHeight: number;
108
+ /** 源文件设定帧率 */
109
+ fps: number;
110
+ /** 总帧数 */
111
+ frames: number;
112
+ };
113
+ /**
114
+ * SVGA 版本号
115
+ */
116
+ version?: string;
117
+ /** 图层与精灵序列数据 */
118
+ sprites: any[];
119
+ /** 解码后的图片位图映射表 */
120
+ images?: Record<string, ImageBitmap | Uint8Array | HTMLImageElement | null>;
121
+ /** 保存原始字节给 Worker 使用 */
122
+ imageBytes?: Record<string, Uint8Array>;
123
+ /** 解析时的原始 SVGA 文件大小(字节) */
124
+ fileSize?: number;
125
+ /** 统一 Web Worker 缓存专用的高速唯一缓存 Key */
126
+ movieDataId?: string;
127
+ }
98
128
  interface ParserDestroyOptions {
99
129
  /** 指定清除缓存的特定 URL */
100
130
  url?: string;
@@ -106,113 +136,117 @@ interface ParserDestroyOptions {
106
136
  interface WorkerConfig {
107
137
  /** 自定义 Web Worker 的 URL 地址 */
108
138
  workerUrl?: string;
109
- /** 自定义创建 Web Worker 实例的工厂函数,优先级高于 workerUrl */
139
+ /** 自定义创建 Web Worker 实例的工厂函数,优先级最高 */
110
140
  workerCreator?: () => Worker;
141
+ /** 直接传入一个已实例化的 Web Worker 实例 */
142
+ workerInstance?: Worker;
143
+ /** 内联的 Web Worker 源码字符串,用于打包时零配置直接实例化 */
144
+ workerString?: string;
111
145
  }
112
-
113
- declare class Parser {
114
- /**
115
- * 获取已缓存的动画数据(同步)
116
- * @param url 需要获取的缓存 key 地址
117
- */
118
- static getCachedVideoItem(url: string): any;
119
- /**
120
- * 加载网络资源,内置 LRU / 字典缓存机制
121
- * @param url SVGA 文件在线地址
122
- * @param options 参数配置选项,包含 useImageBitmap 和 cache。cache 默认为 true。
123
- */
124
- static loadUrl(url: string, options?: {
125
- useImageBitmap?: boolean;
126
- movieDataId?: string;
127
- cache?: boolean;
128
- }): Promise<any>;
129
- /**
130
- * 加载本地文件(本地文件通常不存共享缓存)
131
- * @param file 本地 File 对象
132
- * @param options 参数配置选项,支持 useImageBitmap 与 cache
133
- */
134
- static loadFile(file: File | Blob, options?: {
135
- useImageBitmap?: boolean;
136
- cache?: boolean;
137
- }): Promise<any>;
138
- /**
139
- * 使用共享 Web Worker 解析 SVGA ArrayBuffer
140
- * @param buffer 载入的 ArrayBuffer 文件数据
141
- * @param options 参数配置选项,包含 useImageBitmap, movieDataId 以及 cache
142
- * @returns 解析出的 MovieEntity 数据
143
- */
144
- static parseBuffer(buffer: ArrayBuffer, options?: {
145
- useImageBitmap?: boolean;
146
- movieDataId?: string;
147
- cache?: boolean;
148
- }): Promise<any>;
149
- /**
150
- * 专用于离屏渲染的加载方法 (Worker-only offscreen render pipeline)
151
- * 此方法内,所有的精灵图层、Proto 解码与最终的 ImageBitmap 直接留在子线程缓存中,
152
- * 绝对不传输/拷贝回主线程,只返回轻量级元数据数据 `{ movieDataId, isOffscreen: true, params: { ... } }`
153
- *
154
- * @param url SVGA 文件在线地址
155
- * @param options 参数配置,默认开启缓存
156
- */
157
- static load(url: string, options?: {
158
- cache?: boolean;
159
- }): Promise<{
160
- movieDataId: string;
161
- isOffscreen: true;
162
- params: {
163
- viewBoxWidth: number;
164
- viewBoxHeight: number;
165
- fps: number;
166
- frames: number;
167
- };
168
- }>;
169
- /**
170
- * 使用共享 Web Worker 仅在子线程解析并留存 SVGA 离屏渲染数据
171
- */
172
- static parseBufferOffscreen(buffer: ArrayBuffer, movieDataId: string, options?: {
173
- cache?: boolean;
174
- }): Promise<{
175
- movieDataId: string;
176
- isOffscreen: true;
177
- params: {
178
- viewBoxWidth: number;
179
- viewBoxHeight: number;
180
- fps: number;
181
- frames: number;
182
- };
183
- }>;
184
- /**
185
- * 释放指定的主线程传统渲染缓存,防止 H5 长期运行导致内存/显存溢出
186
- * @param url 需要清理的缓存 key
187
- */
188
- static destroyCache(url: string): void;
189
- /**
190
- * 清空所有主线程传统渲染的动画缓存数据
191
- */
192
- static clearCache(): void;
193
- /**
194
- * 释放指定的离屏渲染缓存(包含 Worker 子线程中的解码缓存)
195
- * @param movieDataId 缓存中的唯一标识 ID(即 load 方法返回的 movieDataId)
196
- * @param force 是否强制销毁(若为 true,即使引用计数大于 0 也会被强行清理)
197
- */
198
- static destroyOffscreenCache(movieDataId: string, force?: boolean): void;
199
- /**
200
- * 清空所有离屏渲染的动画缓存数据,并通知 Worker 彻底释放所有缓存
201
- */
202
- static clearOffscreenCache(): void;
203
- /**
204
- * 销毁并清除主线程和子线程中的缓存。
205
- * - 不传参数:默认全量清空主线程与子线程的所有动画缓存。
206
- * - 传入字符串 URL:双端(主、子线程)中清空对应 URL 的动画缓存。
207
- * - 传入 options 选项:支持配置可选 url 参数,有是否清除主线程/子线程所有缓存等配置。
208
- */
209
- static destroy(arg?: string | ParserDestroyOptions): void;
210
- /**
211
- * 配置全局共享的 Web Worker。
212
- * 支持通过自定义 URL 或 Worker 创建工厂函数配置,利于在 IIFE/CommonJS 等不原生支持 import.meta.url 的环境中运行。
213
- * @param config Web Worker 配置参数
214
- */
215
- static setWorkerConfig(config: WorkerConfig): void;
146
+ interface IRenderer {
147
+ observerIsVisible: boolean;
148
+ onStart?: () => void;
149
+ onPause?: () => void;
150
+ onStop?: () => void;
151
+ onLoopEnd?: () => void;
152
+ onProcess?: (frame: number) => void;
153
+ setMovie(movieData: MovieData): void | Promise<void>;
154
+ setImage(image: HTMLImageElement | ImageBitmap | HTMLCanvasElement, key: string): void | Promise<void>;
155
+ setDynamicText(text: DynamicText, key: string): void;
156
+ setShapeRenderer(renderer: any): void;
157
+ drawExternalPoster(imageUrl: string): Promise<void>;
158
+ play(config?: PlayConfig): void;
159
+ stop(): void;
160
+ pause(): void;
161
+ stepToFrame(frame: number, andPlay?: boolean): void;
162
+ stepToPercentage(percentage: number, andPlay?: boolean): void;
163
+ clear(): void;
164
+ clearDynamicObject(key: string): void;
165
+ clearDynamicObjects(): void;
166
+ getMemoryInfo(): {
167
+ fileSize: number;
168
+ imageMemory: number;
169
+ dictionaryMemory: number;
170
+ version: string;
171
+ fps: number;
172
+ frames: number;
173
+ width: number;
174
+ height: number;
175
+ dynamicKeys: string[];
176
+ desc: string;
177
+ };
178
+ destroy(): void;
179
+ }
180
+ /**
181
+ * Worker 收到的指令动作类型
182
+ */
183
+ declare enum WORKER_ACTION {
184
+ /** 初始化渲染画布 */
185
+ INIT = "init",
186
+ /** 更新可见性 */
187
+ VISIBILITY = "visibility",
188
+ /** 设置电影元数据 */
189
+ SET_MOVIE = "setMovie",
190
+ /** 设置替换图片位图 */
191
+ SET_IMAGE = "setImage",
192
+ /** 设置自定义动态文本 */
193
+ SET_DYNAMIC_TEXT = "setDynamicText",
194
+ /** 绘制外部背景背景图 */
195
+ DRAW_EXTERNAL_POSTER = "drawExternalPoster",
196
+ /** 开始播放 */
197
+ PLAY = "play",
198
+ /** 停止播放 */
199
+ STOP = "stop",
200
+ /** 暂停播放 */
201
+ PAUSE = "pause",
202
+ /** 跳跃至指定帧 */
203
+ STEP_TO_FRAME = "stepToFrame",
204
+ /** 跳跃至指定百分比 */
205
+ STEP_TO_PERCENTAGE = "stepToPercentage",
206
+ /** 擦除画布 */
207
+ CLEAR = "clear",
208
+ /** 重置动态内容 */
209
+ CLEAR_DYNAMIC_OBJECTS = "clearDynamicObjects",
210
+ /** 清除某个指定的动态替换属性 */
211
+ CLEAR_DYNAMIC_OBJECT = "clearDynamicObject",
212
+ /** 卸载销毁实例 */
213
+ DESTROY = "destroy",
214
+ /** 解析 SVGA 数据 */
215
+ PARSE = "parse",
216
+ /** 解析离屏 SVGA 数据 */
217
+ PARSE_OFFSCREEN = "parse_offscreen",
218
+ /** 释放 Parser 内存缓存 */
219
+ RELEASE_CACHE = "releaseCache"
220
+ }
221
+ /**
222
+ * Worker 发回主线程的消息分类
223
+ */
224
+ declare enum WORKER_RESPONSE_TYPE {
225
+ /** 操作执行成功 */
226
+ SUCCESS = "SUCCESS",
227
+ /** 发生运行异常 */
228
+ ERROR = "ERROR",
229
+ /** 渲染器事件通知 */
230
+ EVENT = "event"
231
+ }
232
+ /**
233
+ * 动效播放生命周期事件名称
234
+ */
235
+ declare enum SVGA_EVENT_NAME {
236
+ /** 渲染就绪 */
237
+ READY = "ready",
238
+ /** 播放启动 */
239
+ ON_START = "onStart",
240
+ /** 播放中止 */
241
+ ON_STOP = "onStop",
242
+ /** 播放暂停 */
243
+ ON_PAUSE = "onPause",
244
+ /** 单帧前行回调 */
245
+ ON_PROCESS = "onProcess",
246
+ /** 单轮循环结束 */
247
+ ON_LOOP_END = "onLoopEnd",
248
+ /** 离屏绘制通知主线程补全数据 */
249
+ ON_REQUEST_MOVIE_DATA = "onRequestMovieData"
216
250
  }
217
251
 
218
252
  declare class Player {
@@ -328,4 +362,116 @@ declare class Player {
328
362
  destroy(): void;
329
363
  }
330
364
 
331
- export { Parser, Player };
365
+ declare class Parser {
366
+ /**
367
+ * 获取已缓存的动画数据(同步)
368
+ * @param url 需要获取的缓存 key 地址
369
+ */
370
+ static getCachedVideoItem(url: string): any;
371
+ /**
372
+ * 加载网络资源,内置 LRU / 字典缓存机制
373
+ * @param url SVGA 文件在线地址
374
+ * @param options 参数配置选项,包含 useImageBitmap 和 cache。cache 默认为 true。
375
+ */
376
+ static loadUrl(url: string, options?: {
377
+ useImageBitmap?: boolean;
378
+ movieDataId?: string;
379
+ cache?: boolean;
380
+ }): Promise<any>;
381
+ /**
382
+ * 加载本地文件(本地文件通常不存共享缓存)
383
+ * @param file 本地 File 对象
384
+ * @param options 参数配置选项,支持 useImageBitmap 与 cache
385
+ */
386
+ static loadFile(file: File | Blob, options?: {
387
+ useImageBitmap?: boolean;
388
+ cache?: boolean;
389
+ }): Promise<any>;
390
+ /**
391
+ * 使用共享 Web Worker 解析 SVGA ArrayBuffer
392
+ * @param buffer 载入的 ArrayBuffer 文件数据
393
+ * @param options 参数配置选项,包含 useImageBitmap, movieDataId 以及 cache
394
+ * @returns 解析出的 MovieEntity 数据
395
+ */
396
+ static parseBuffer(buffer: ArrayBuffer, options?: {
397
+ useImageBitmap?: boolean;
398
+ movieDataId?: string;
399
+ cache?: boolean;
400
+ }): Promise<any>;
401
+ /**
402
+ * 专用于离屏渲染的加载方法 (Worker-only offscreen render pipeline)
403
+ * 此方法内,所有的精灵图层、Proto 解码与最终的 ImageBitmap 直接留在子线程缓存中,
404
+ * 绝对不传输/拷贝回主线程,只返回轻量级元数据数据 `{ movieDataId, isOffscreen: true, params: { ... } }`
405
+ *
406
+ * @param url SVGA 文件在线地址
407
+ * @param options 参数配置,默认开启缓存
408
+ */
409
+ static load(url: string, options?: {
410
+ cache?: boolean;
411
+ }): Promise<{
412
+ movieDataId: string;
413
+ isOffscreen: true;
414
+ params: {
415
+ viewBoxWidth: number;
416
+ viewBoxHeight: number;
417
+ fps: number;
418
+ frames: number;
419
+ };
420
+ }>;
421
+ /**
422
+ * 使用共享 Web Worker 仅在子线程解析并留存 SVGA 离屏渲染数据
423
+ */
424
+ static parseBufferOffscreen(buffer: ArrayBuffer, movieDataId: string, options?: {
425
+ cache?: boolean;
426
+ }): Promise<{
427
+ movieDataId: string;
428
+ isOffscreen: true;
429
+ params: {
430
+ viewBoxWidth: number;
431
+ viewBoxHeight: number;
432
+ fps: number;
433
+ frames: number;
434
+ };
435
+ }>;
436
+ /**
437
+ * 释放指定的主线程传统渲染缓存,防止 H5 长期运行导致内存/显存溢出
438
+ * @param url 需要清理的缓存 key
439
+ */
440
+ static destroyCache(url: string): void;
441
+ /**
442
+ * 清空所有主线程传统渲染的动画缓存数据
443
+ */
444
+ static clearCache(): void;
445
+ /**
446
+ * 释放指定的离屏渲染缓存(包含 Worker 子线程中的解码缓存)
447
+ * @param movieDataId 缓存中的唯一标识 ID(即 load 方法返回的 movieDataId)
448
+ * @param force 是否强制销毁(若为 true,即使引用计数大于 0 也会被强行清理)
449
+ */
450
+ static destroyOffscreenCache(movieDataId: string, force?: boolean): void;
451
+ /**
452
+ * 清空所有离屏渲染的动画缓存数据,并通知 Worker 彻底释放所有缓存
453
+ */
454
+ static clearOffscreenCache(): void;
455
+ /**
456
+ * 销毁并清除主线程和子线程中的缓存。
457
+ * - 不传参数:默认全量清空主线程与子线程的所有动画缓存。
458
+ * - 传入字符串 URL:双端(主、子线程)中清空对应 URL 的动画缓存。
459
+ * - 传入 options 选项:支持配置可选 url 参数,有是否清除主线程/子线程所有缓存等配置。
460
+ */
461
+ static destroy(arg?: string | ParserDestroyOptions): void;
462
+ /**
463
+ * 配置全局共享的 Web Worker。
464
+ * 支持通过自定义 URL 或 Worker 创建工厂函数配置,利于在 IIFE/CommonJS 等不原生支持 import.meta.url 的环境中运行。
465
+ * @param config Web Worker 配置参数
466
+ */
467
+ static setWorkerConfig(config: WorkerConfig): void;
468
+ }
469
+
470
+ /**
471
+ * 设置全局共享的 Web Worker 配置
472
+ * @param config Web Worker 的自定义 URL 或实例化工厂方法
473
+ */
474
+ declare function setWorkerConfig(config: WorkerConfig): void;
475
+
476
+ export { Parser, Player, SVGA_EVENT_NAME, WORKER_ACTION, WORKER_RESPONSE_TYPE, setWorkerConfig };
477
+ export type { DynamicText, IRenderer, MovieData, ParserDestroyOptions, PlayConfig, WorkerConfig };