屏幕红色转黑色淡入淡出效果仅生效一次的原因排查
红色到黑色淡入淡出效果重复调用失效问题解决
问题场景
我实现了一个从红色透明渐变到黑色的屏幕淡入淡出效果,首次调用功能正常,但后续重置状态后再次调用,效果完全失效。相关代码如下:
原效果类代码
export class FadeEffects { constructor(game) { this.game = game; this.width = 640; this.height = 480; this.fadeFinished = false; this.fade = 255; } // 从红色透明渐变到黑色 fadeRed() { let fadeOut = setInterval(() => { console.log('in interval'); this.fade -= 1; if (this.fade === 0) { this.fade = 255; this.fadeFinished = true; clearInterval(fadeOut); } }, 25); return this.fadeFinished; } draw(context) { context.fillStyle = "rgba(" + this.fade + ", 0, 0, 0.5"; context.fillRect(0, 0, this.width, this.height); } }
原调用逻辑
if(!this.fadeFinished && toRemove === 'TRUE'){ this.fadeFinished = this.fadeEffect.fadeRed(); this.fadeEffect.draw(context); }
核心问题分析
- 异步状态同步错误:
setInterval是异步执行的,调用fadeRed()时会立刻返回初始的fadeFinished(false),后续异步修改的fadeFinished无法同步到调用处的赋值,导致调用逻辑里的this.fadeFinished被错误设为false,判断逻辑彻底混乱。 - 重复创建定时器:每次满足调用条件时都会执行
fadeRed(),创建多个定时器同时修改this.fade,状态被反复干扰,即使重置fadeFinished,多个定时器的叠加也会让效果异常。 - 调用逻辑重复触发:只要
!this.fadeFinished && toRemove === 'TRUE',就会反复调用fadeRed(),短时间内生成大量定时器,直接破坏状态。 - 颜色格式错误:
draw方法里的rgba字符串少了闭合的),存在渲染隐患。
修复方案
修正后的效果类代码
export class FadeEffects { constructor(game) { this.game = game; this.width = 640; this.height = 480; this.fadeFinished = false; this.fade = 255; this.fadeTimer = null; // 存储定时器引用,防止重复创建 } // 从红色透明渐变到黑色 fadeRed() { // 已有定时器在运行时直接返回,避免重复触发 if (this.fadeTimer) return; this.fadeFinished = false; this.fade = 255; // 重置渐变初始值 this.fadeTimer = setInterval(() => { this.fade -= 1; // 用<=0避免因定时器延迟导致的数值跳过0的情况 if (this.fade <= 0) { this.fade = 255; this.fadeFinished = true; clearInterval(this.fadeTimer); this.fadeTimer = null; // 清除引用,允许下次调用 } }, 25); } draw(context) { // 修复rgba格式错误 context.fillStyle = `rgba(${this.fade}, 0, 0, 0.5)`; context.fillRect(0, 0, this.width, this.height); } }
修正后的调用逻辑
// 仅在效果未开始、触发条件满足且无运行中定时器时,启动一次渐变 if (!this.fadeFinished && toRemove === 'TRUE' && !this.fadeEffect.fadeTimer) { this.fadeEffect.fadeRed(); } // 只要渐变未完成,就持续绘制(保证每一帧都更新渐变状态) if (!this.fadeFinished) { this.fadeEffect.draw(context); }
修复说明
- 新增
fadeTimer属性:跟踪当前是否有渐变定时器在运行,彻底避免重复创建定时器的问题。 - 移除
fadeRed()的返回值:直接通过实例属性fadeFinished同步状态,解决异步导致的状态不同步问题。 - 分离绘制逻辑:保证渐变过程中每一帧都能重新绘制,让渐变效果平滑显示。
- 修复
rgba格式错误:确保颜色渲染正常。 - 调整终止条件为
this.fade <= 0:避免因定时器执行延迟导致fade直接跳过0的情况,保证渐变能正确终止。
内容的提问来源于stack exchange,提问作者Jleger91
相关产品推荐
相关产品推荐

