前端开发
PixiJS v8 中运行逐帧逻辑或控制渲染循环时…
适用于 PixiJS v8 项目中需要每帧更新、控制 ticker 渲染循环、调整帧率/速度/优先级或管理 Ticker 实例的场景。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
PixiJS v8 中运行逐帧逻辑或控制特定
解决思路
- 使用 app.ticker.add(callback) 注册每帧回调;回调参数是 Ticker 实例,读取 ticker.deltaTime 作为帧率无关乘数(60fps 约 1.0),或读取 ticker.deltaMS 做真实时间计算。
- Quick Start 操作:在 app.ticker.add((ticker) => { ... }) 中用 sprite.rotation += 0.01 * ticker.deltaTime 做旋转;用 sprite.x += (200 / 1000) * ticker.deltaMS 做像素/秒移动;用 app.ticker.add(callback, undefined, UPDATE_PRIORITY.HIGH) 注册高优先级回调;设置 app.ticker.maxFPS = 30;设置 app.ticker.speed = 0.5;用 sprite.onRender = () => { sprite.scale.x = Math.sin(performance.now() / 500); }; 绑定每对象渲染钩子。
- 选择时间单位:deltaTime 是无量纲值(约 1.0 @60fps),会被 speed 缩放并被 minFPS 限制,用于帧率无关动画乘数;deltaMS 是毫秒,会被 speed 缩放并被 minFPS 限制,用于基于时间的计算(如像素/秒);elapsedMS 是毫秒,不被 speed 缩放、不被 minFPS 限制,用于原始测量/性能分析。
- 理解并处理 deltaTime 不是毫秒:deltaTime = deltaMS * Ticker.targetFPMS,其中 targetFPMS 是 0.06(即 1/16.67);60fps 时 deltaTime 为 1.0,30fps 时为 2.0,所以不要把它当作时间值。
- 按 UPDATE_PRIORITY 注册回调以控制顺序:INTERACTION(50) > HIGH(25) > NORMAL(0) > LOW(-25) > UTILITY(-50);app.render() 由 TickerPlugin 注册在 LOW。用 app.ticker.add(fn, undefined, UPDATE_PRIORITY.HIGH) 让物理等先于普通回调;默认 NORMAL=0 在 HIGH 后、render 前运行。
- 类方法作为 ticker 回调时,把 this 作为第二个参数传入:app.ticker.add(system.update, system);移除时用 app.ticker.remove(system.update, system),必须函数和上下文都匹配。
- 帧率封顶:用 new Ticker() 创建实例,设置 ticker.maxFPS = 30 通过跳帧维持上限;设置 ticker.minFPS = 10 限制 deltaTime/deltaMS,避免大帧掉落产生巨大增量(默认 minFPS 为 10);如果 maxFPS < minFPS,minFPS 会降到匹配,如果 minFPS > maxFPS,maxFPS 会提升匹配。
- 每对象 onRender 钩子:设置 sprite.onRender = (renderer) => { sprite.rotation += 0.01; };它在场景图遍历期间、GPU 渲染前调用;当逐帧逻辑绑定到特定显示对象时,用它替代全局 ticker 回调。
- 使用 Ticker.shared 单例;它 autoStart=true 且受保护,调用 destroy() 不会真正销毁。
- 使用 Ticker.system 处理引擎后台任务;它是独立于主场景 ticker 的普通 Ticker 实例(autoStart=true,_protected=true),无内在优先级;监听器通常按约定加到 UTILITY 优先级。
- 创建自定义 new Ticker() 实例:autoStart=false,需要自己管理生命周期;设置 custom.autoStart=true 可在添加第一个监听器时启动;用 custom.add((ticker) => { ... }) 注册;用 custom.addOnce(cb, null, UPDATE_PRIORITY.NORMAL) 注册一次性自动移除回调;结束时调用 custom.stop(); custom.destroy()。
- Application 默认创建自己的 Ticker;在 app.init() 中设置 sharedTicker: true 可改用 Ticker.shared;Ticker.shared 和 Ticker.system 都是 _protected,调用 destroy() 不会真正销毁;读取 ticker.FPS 获取实测帧率,读取 ticker.count 获取当前监听器数量。
- App 生命周期:在 app.init({ autoStart: false }) 后,用 app.start() 和 app.stop() 暂停/恢复内置渲染循环;app.start()/app.stop() 由 TickerPlugin 添加,映射到 ticker.start()/ticker.stop()。
- 手动渲染循环:需要 headless、可见性门控、固定时间步长等时,自己驱动循环:function animate() { app.ticker.update(); app.render(); requestAnimationFrame(animate); } animate(); 配合 autoStart: false 可在 tab 失焦暂停、固定时间步长循环或离屏渲染时使用。
- 速度缩放:设置 app.ticker.speed = 0.5 做半速/慢动作;设置 app.ticker.speed = 2.0 做双倍速;speed 影响 deltaTime 和 deltaMS,但不影响 elapsedMS。
- 避免 CRITICAL 错误:ticker 回调第一个参数不是 delta 数字,而是 Ticker 实例。错误:app.ticker.add((dt) => { bunny.rotation += dt; }); 正确:app.ticker.add((ticker) => { bunny.rotation += ticker.deltaTime; }); v8 中 v7 的 (dt) => ... 模式会编译,但 dt 是整个 Ticker 对象,算术结果为 NaN。
- 避免 HIGH 错误:不要用 updateTransform 做每帧逻辑,v8 已移除 updateTransform;正确做法是在 constructor 中 this.onRender = this._onRender.bind(this),并定义 private _onRender() { this.rotation += 0.01; },用 onRender 处理每对象每帧逻辑。
- 避免 MEDIUM 错误:不要把 deltaTime 当毫秒。错误:sprite.x += (100 * ticker.deltaTime) / 1000; 正确:sprite.x += (100 / 1000) * ticker.deltaMS; 或 sprite.x += 1.5 * ticker.deltaTime; 用 deltaMS 做真实时间计算,用 deltaTime 作为「60fps 每帧」行为的乘数。
- 需要查 API 时参考官方文档:Ticker https://pixijs.download/release/docs/ticker.Ticker.html.md,TickerPlugin https://pixijs.download/release/docs/app.TickerPlugin.html.md,TickerPluginOptions https://pixijs.download/release/docs/app.TickerPluginOptions.html.md。
适用边界 · 注意事项
- 不适用于未使用 PixiJS v8 的项目;其他渲染框架或引擎不能直接套用。
- 项目仍基于 PixiJS v7 时,Ticker 回调签名不同,需先迁移,不要直接按 v8 写法使用。
- 若不需要逐帧逻辑、渲染循环控制、帧率/速度/优先级或 Ticker 生命周期管理,则无需使用这些操作。