尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

PixiJS v8 GifSprite 实战指南:GIF 动图加载、播放控制与资源释放

PixiJS v8 GifSprite 实战指南:GIF 动图加载、播放控制与资源释放 PixiJS v8 GifSprite 实战指南GIF 动图加载、播放控制与资源释放【免费下载链接】pixijsThe HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.项目地址: https://gitcode.com/gh_mirrors/pi/pixijs导读本指南聚焦 PixiJS v8 中播放 GIF 动图的标准方案通过pixi.js/gif副作用导入注册加载器扩展用Assets.load得到GifSource再交由GifSprite播放。文章完整覆盖构造选项、播放 API、回调、手动更新、source 共享与克隆、销毁清理等实战要点并结合仓库源码GifSprite.ts、GifSource.ts、GifAsset.ts与测试用例GifSprite.test.ts、GifAsset.test.ts讲解底层原理。读完你可以在 PixiJS v8 项目中独立接入并精细控制 GIF 动图。前置知识阅读本文前建议先了解 pixijs-scene-core-concepts场景图基础、pixijs-assetsAssets.load与缓存/卸载、pixijs-ticker帧计时以及 pixijs-performance纹理内存。GifSprite继承自Sprite是叶子节点allowChildren false不能在其中嵌套子对象如需组合多个 GIF请用普通Container包裹。Quick Start三步播放一个 GIFimport pixi.js/gif; import { GifSprite } from pixi.js/gif; const source await Assets.load(animation.gif); const gif new GifSprite({ source, autoPlay: true, loop: true, animationSpeed: 1, }); gif.anchor.set(0.5); gif.x app.screen.width / 2; gif.y app.screen.height / 2; app.stage.addChild(gif);核心要点Assets.load(animation.gif)返回的是GifSource不是Texture必须包在GifSprite中使用。仓库中的可运行示例见 examples/sprite_gif_animation_loading.ts它展示了完整的Application初始化、Assets.load远程 GIF 与GifSprite挂载流程。[!NOTE] GIF 的每一帧都会被解码成独立的 canvas 纹理。对于帧数多、性能敏感的动画优先使用精灵图集 AnimatedSprite见 pixijs-scene-sprite 与 animated-sprite 相关示例——图集是单一纹理GPU 合批更高效。构造选项GifSpriteOptionsGifSpriteOptions继承自OmitSpriteOptions, texture——texture由内部管理初始设为source.textures[0]逐帧切换因此所有Sprite选项anchor、scale、tint、roundPixels等以及所有Container选项position、scale、label、filters、zIndex等都合法详见 constructor-options.md。GifSpriteOptions新增的动图专属选项选项类型默认值说明sourceGifSource—必填。Assets.load(file.gif)返回的解析后 GIF 数据可在多个GifSprite实例间共享autoPlaybooleantrue构造后立即开始播放为false时必须手动调用gif.play()loopbooleantrue播到最后一帧后循环为false时停在最后一帧并触发onCompleteanimationSpeednumber1对 GIF 原生帧时长的倍率。2为双倍速0.5为半速autoUpdatebooleantrue将播放挂接到Ticker.shared设为false后由你自行调用gif.update(ticker)驱动fpsnumber30当 GIF 未指定每帧延迟时的回退帧率onComplete() void \| nullnull非循环动画到达最后一帧时触发onLoop() void \| nullnull每次循环动画绕回开头时触发onFrameChange(frame: number) void \| nullnull每次显示帧索引变化时触发scaleModeSCALE_MODElinear自 8.13.0 起废弃——改为通过Assets.load(..., { data: { scaleMode } })传入这些默认值在源码中定义为 GifSprite.defaultOptions构造时会与传入选项合并Object.assign({}, GifSprite.defaultOptions, options)因此你也可以全局修改默认行为例如GifSprite.defaultOptions.fps 24。另外构造器也接受直接传入一个裸GifSourcenew GifSprite(source)等价于new GifSprite({ source })见 GifSprite.ts 构造器重载。测试 GifSprite.test.ts 同时验证了两种构造方式以及 Sprite 选项如x、y的透传。核心模式1. 副作用导入与加载器注册import pixi.js/gif; import { Assets } from pixi.js; import { GifSprite } from pixi.js/gif; const source await Assets.load(animation.gif); const gif new GifSprite({ source });pixi.js/gif入口src/gif/init.ts内部执行extensions.add(GifAsset)将.gif注册进资源加载器。GifAssetGifAsset.ts是一个ExtensionType.Asset扩展其 loader 的匹配规则为扩展名.gif或data:image/gif开头的 URItest: (url) path.extname(url) .gif || url.startsWith(data:image/gif), load: async (url, asset) { const response await DOMAdapter.get().fetch(url); const buffer await response.arrayBuffer(); return GifSource.from(buffer, asset?.data); },没有这个副作用导入Assets.load不识别 GIF 文件加载会失败或返回原始数据。注意GifSprite与GifSource均从pixi.js/gif导出见 src/gif/index.ts而不是pixi.js主包只要从pixi.js/gif导入任意具名导出副作用就已触发裸import pixi.js/gif仅在你不需要该路径下任何导出时才必须显式书写。2. 播放控制const gif new GifSprite({ source }); gif.play(); gif.stop(); gif.currentFrame 5; gif.animationSpeed 2; gif.animationSpeed 0.5; gif.playing; // 只读 gif.progress; // 0-1 播放位置 gif.totalFrames; // 总帧数 gif.duration; // 总时长毫秒autoPlay: true默认构造即播放loop: true默认循环播放animationSpeed是原生帧时长的倍率currentFrame为从 0 开始的索引越界会抛出Frame index out of range异常见 GifSprite.ts 的 _updateFrameIndex测试中也有对应断言progress基于_currentTime / duration计算适合驱动进度条duration取最后一帧的end时间毫秒totalFrames透传自GifSource。底层驱动逻辑在 GifSprite.update每个 tick 计算elapsed animationSpeed * ticker.deltaTime / Ticker.targetFPMS累加到_currentTime再通过frame.start localTime frame.end localTime找到当前帧到达末尾时分循环重置时间并触发onLoop与非循环钉在最后一帧、触发onComplete并stop()两条路径处理。渲染时onRender钩子调用_updateFrame仅在dirty为真时切换this.texture指向当前帧纹理GifSprite.ts避免每帧无谓重绘。3. 加载选项const source await Assets.load({ src: animation.gif, data: { fps: 12, scaleMode: nearest, resolution: 2, }, }); const fromDataUri await Assets.load(data:image/gif;base64,R0lGODlh...);data中的选项会原样传给GifSource.fromasset?.data即上文 loader 实现中的透传。其中fpsGIF 未标注帧延迟时的回退帧率源码中换算为defaultDelay 1000 / fpsGifSource.tsscaleMode与resolution控制每帧生成的 canvas 纹理的缩放模式与分辨率透传给CanvasSource构造...canvasSourceOptions。加载器同时匹配.gif文件扩展名与data:image/gifURI测试 GifAsset.test.ts 验证了文件加载、base64 加载以及带data: { fps }选项加载三种场景并确认Assets.unload后source.frames与source.textures被置空。注意scaleMode已废弃作为GifSprite选项请统一在Assets.load的data中指定。4. 回调const gif new GifSprite({ source, loop: false, onComplete: () console.log(animation finished), onLoop: () console.log(loop completed), onFrameChange: (frame) console.log(now on frame, frame), });onComplete非循环动画到达最后一帧时触发onLoop循环动画每次绕回开头时触发onFrameChange显示帧每次变化时触发_updateFrameIndex中在帧索引真正变化时调用并置dirty。5. 手动更新模式const gif new GifSprite({ source, autoUpdate: false }); app.ticker.add((ticker) { gif.update(ticker); });autoUpdate: false会断开与Ticker.shared的连接由你自行调用gif.update(ticker)并传入任意Ticker实例。适用于由私有 ticker 驱动动画的场景例如带暂停逻辑的游戏 ticker。autoUpdate也可在运行时动态切换置false会从共享 ticker 移除置true且正在播放时重新挂接见 GifSprite.ts 的 autoUpdate setter。播放挂接时使用UPDATE_PRIORITY.HIGH优先级GifSprite.play。6. 共享 source 与克隆const source await Assets.load(animation.gif); const gif1 new GifSprite({ source, autoPlay: true }); const gif2 new GifSprite({ source, autoPlay: false }); const gif3 gif1.clone(); gif3.animationSpeed 0.5;GifSource可在多个GifSprite实例间共享类似多个Sprite共享一个Texture每个 sprite 的播放状态相互独立。clone()会复制全部播放设置autoUpdate、loop、autoPlay、animationSpeed、三个回调并创建一个独立实例GifSprite.clone测试 GifSprite.test.ts 验证了克隆保留选项但不保留播放状态——原 sprite 处于停止时克隆默认playing为true因为autoPlay默认开启。GifSource本身还暴露width、height、duration、totalFrames、frames、textures等只读属性以及从 ArrayBuffer 手工构建的静态方法GifSource.from(buffer, options)便于绕过Assets直接 fetch 二进制后创建GifSource.ts。常见错误[HIGH] 忘记导入 pixi.js/gif错误写法import { Assets } from pixi.js; const gif await Assets.load(animation.gif);正确写法import pixi.js/gif; import { Assets } from pixi.js; const source await Assets.load(animation.gif);GIF 加载器扩展必须在加载之前注册。没有副作用导入加载器不识别.gif文件加载会失败或返回原始数据。[MEDIUM] 误以为 Assets.load 返回 Texture错误写法const texture await Assets.load(animation.gif); const sprite new Sprite(texture);正确写法const source await Assets.load(animation.gif); const gif new GifSprite({ source });对 GIF 调用Assets.load返回的是包含帧纹理与计时数据的GifSource请把它传给GifSprite若只需要某一静止帧读取source.textures[0]即可。[MEDIUM] destroy 后 GIF 内存未释放错误写法gif.destroy(); // GifSource 与各帧纹理仍驻留内存正确写法gif.destroy(true); // 或 await Assets.unload(animation.gif);GIF 的每一帧都以独立 canvas 纹理持有解码后的像素数据源码见 GifSource.from逐帧getImageData→putImageData到新 canvas 再包装为TextureCanvasSource。gif.destroy()即destroy(false)只销毁 spriteGifSource原样保留传入true会连带销毁 sourceGifSprite.destroy其内部调用this._source.destroy()清空所有帧纹理。测试明确断言destroy()后source.duration/totalFrames不变而destroy(true)后归零。对于被共享的 source只在最后一个使用者结束时销毁或交给Assets.unload由资源缓存统一处理卸载会调用 loader 的unload钩子执行asset.destroy()。[LOW] 不要把子对象嵌套进 GifSpriteGifSprite继承自SpriteallowChildren false是叶子节点。要将 GIF 与其他显示对象组合请统一包进普通Containerconst group new Container(); group.addChild(gif, label);深入GifSource 的帧解码管线GifSource.from内部依赖gifuct-js完成解析与解压parseGIFdecompressFrames随后在内存 canvas 上完成帧合成处理disposalType缺省按 2 即清除处理、用delay缺省1000 / fps计算每帧start/end时间戳、将每帧渲染到独立CanvasSource纹理并组装成GifFrame[]GifSource.ts。GifFrame由texture、start、end组成GifBufferOptions则是除resource外的CanvasSourceOptions加上fps回退项。理解了这条管线就能明白为什么每个帧都是独立 canvas 纹理——这也是大帧数 GIF 内存开销高的根源与性能敏感场景改用精灵图集的建议一脉相承。总结在 PixiJS v8 中使用 GIF 动图的完整链路为import pixi.js/gif注册GifAsset→Assets.load得到GifSource→new GifSprite({ source, ... })播放。掌握autoPlay/loop/animationSpeed与play/stop/currentFrame等播放控制、三个生命周期回调、autoUpdate手动驱动、source 共享与克隆以及destroy(true)/Assets.unload的资源释放纪律即可在生产场景中安全高效地使用 GIF 动图。API 参考对应源码位置仓库内GifSprite含GifSpriteOptions接口定义与全部播放 APIGifSource含GifBufferOptions、GifFrame与GifSource.fromGifAsset加载器扩展注册与匹配规则init.tsextensions.add(GifAsset)副作用入口测试GifSprite.test.ts、GifSource.test.ts、GifAsset.test.ts示例sprite_gif_animation_loading.ts【免费下载链接】pixijsThe HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.项目地址: https://gitcode.com/gh_mirrors/pi/pixijs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表