fix(menu) 修复切换页面时特效未及时清理的问题

This commit is contained in:
chicrobot committed 2026-01-20 14:47:57 +08:00
1 parent 0765e44a02
commit 556d576060
1 file changed
+162 -2
+162 -2
View File
@@ -63,6 +63,9 @@ export default class MenuScene extends Phaser.Scene {
// 添加雨天效果控制按钮 // 添加雨天效果控制按钮
this.createRainControlButton(); this.createRainControlButton();
// 添加页面可见性变化监听,处理页面切出和切回的情况
this.setupVisibilityChangeHandler();
} }
/** /**
@@ -188,7 +191,7 @@ export default class MenuScene extends Phaser.Scene {
// 控制雨滴和涟漪的显示/隐藏 // 控制雨滴和涟漪的显示/隐藏
this.updateRainEffectVisibility(); this.updateRainEffectVisibility();
// 如果关闭雨天效果,清除所有与涟漪相关的延迟调用 // 如果关闭雨天效果,清除所有与涟漪相关的延迟调用、Tween动画和涟漪对象
if (!this.isRainEnabled) { if (!this.isRainEnabled) {
// 清除所有涟漪相关的setTimeout // 清除所有涟漪相关的setTimeout
this.rippleTimeouts.forEach(timeoutId => { this.rippleTimeouts.forEach(timeoutId => {
@@ -196,12 +199,91 @@ export default class MenuScene extends Phaser.Scene {
}); });
// 清空timeout ID数组 // 清空timeout ID数组
this.rippleTimeouts = []; this.rippleTimeouts = [];
// 清除所有与涟漪相关的Tween动画
this.tweens.killTweensOf(this.rippleGroup.getChildren());
// 彻底清除所有涟漪对象
this.rippleGroup.children.each(ripple => {
if (ripple && ripple.active) {
ripple.destroy();
}
});
// 清空涟漪组
this.rippleGroup.clear(true, true);
} }
// 如果重新开启雨天效果,重新启动涟漪生成 // 如果重新开启雨天效果,重新启动涟漪生成
else { else {
// 重新启动涟漪生成
this.createRainRipples(this.screenWidth, this.screenHeight); this.createRainRipples(this.screenWidth, this.screenHeight);
// 检查并重新启动雨滴的Tween动画(如果需要)
this.rainGroup.children.each(raindrop => {
// 检查雨滴是否存在且激活
if (raindrop && raindrop.active) {
// 获取雨滴的当前Tween动画
const tweens = this.tweens.getTweensOf(raindrop);
// 如果没有运行中的Tween动画,重新创建雨滴动画
if (tweens.length === 0) {
// 水平方向的位移量(相对单位),固定向左下方倾斜
const horizontalOffset = -this.unit * Phaser.Math.Between(15, 17); // 固定向左方向,8-12单位
// 重新设置雨滴动画
this.tweens.add({
targets: raindrop,
x: raindrop.x + horizontalOffset, // 水平方向位移
y: this.screenHeight + this.unit * 2, // 垂直方向位移
duration: Phaser.Math.Between(1000, 1050), // 随机下落速度
ease: 'Linear',
repeat: -1, // 无限重复
delay: Phaser.Math.Between(0, 2000), // 随机延迟,使雨滴分布更均匀
onRepeat: (tween, targets) => {
// 检查目标是否存在,防止场景重启时的错误
if (targets[0] && targets[0].active) {
// 重置雨滴位置,考虑到斜向下落,初始x位置可以稍微超出屏幕边缘(相对单位)
const initialX = Phaser.Math.Between(-this.unit * 10, this.screenWidth + this.unit * 10);
targets[0].x = initialX;
targets[0].y = -this.unit * 2;
// 更新动画的x目标值
tween.data[0].value = initialX + horizontalOffset;
} }
} }
});
}
}
});
}
}
/**
* 设置页面可见性变化处理器
*/
setupVisibilityChangeHandler() {
// 保存当前场景的引用
const scene = this;
// 页面可见性变化事件处理函数
const handleVisibilityChange = () => {
if (document.hidden) {
// 页面变为不可见时
scene.onPageHidden();
} else {
// 页面变为可见时
scene.onPageVisible();
}
};
// 添加事件监听器
document.addEventListener('visibilitychange', handleVisibilityChange);
// 在场景销毁时移除事件监听器,防止内存泄漏
this.events.on('destroy', () => {
document.removeEventListener('visibilitychange', handleVisibilityChange);
});
}
/** /**
* 更新雨天效果的可见性 * 更新雨天效果的可见性
@@ -218,6 +300,83 @@ export default class MenuScene extends Phaser.Scene {
}); });
} }
/**
* 页面变为不可见时的处理逻辑
*/
onPageHidden() {
// 如果雨天效果是开启的,清除所有涟漪相关的延迟调用、Tween动画和涟漪对象
if (this.isRainEnabled) {
// 清除所有涟漪相关的setTimeout
this.rippleTimeouts.forEach(timeoutId => {
clearTimeout(timeoutId);
});
// 清空timeout ID数组
this.rippleTimeouts = [];
// 清除所有与涟漪相关的Tween动画
this.tweens.killTweensOf(this.rippleGroup.getChildren());
}
}
/**
* 页面重新变为可见时的处理逻辑
*/
onPageVisible() {
// 如果雨天效果是开启的,重新启动涟漪生成
if (this.isRainEnabled) {
// 清理所有残留的涟漪对象
this.rippleGroup.children.each(ripple => {
if (ripple && ripple.active) {
ripple.destroy();
}
});
// 清空涟漪组
this.rippleGroup.clear(true, true);
// 重新启动涟漪生成
this.createRainRipples(this.screenWidth, this.screenHeight);
// 检查并重新启动雨滴的Tween动画(如果需要)
this.rainGroup.children.each(raindrop => {
// 检查雨滴是否存在且激活
if (raindrop && raindrop.active) {
// 获取雨滴的当前Tween动画
const tweens = this.tweens.getTweensOf(raindrop);
// 如果没有运行中的Tween动画,重新创建雨滴动画
if (tweens.length === 0) {
// 水平方向的位移量(相对单位),固定向左下方倾斜
const horizontalOffset = -this.unit * Phaser.Math.Between(15, 17); // 固定向左方向,8-12单位
// 重新设置雨滴动画
this.tweens.add({
targets: raindrop,
x: raindrop.x + horizontalOffset, // 水平方向位移
y: this.screenHeight + this.unit * 2, // 垂直方向位移
duration: Phaser.Math.Between(1000, 1050), // 随机下落速度
ease: 'Linear',
repeat: -1, // 无限重复
delay: Phaser.Math.Between(0, 2000), // 随机延迟,使雨滴分布更均匀
onRepeat: (tween, targets) => {
// 检查目标是否存在,防止场景重启时的错误
if (targets[0] && targets[0].active) {
// 重置雨滴位置,考虑到斜向下落,初始x位置可以稍微超出屏幕边缘(相对单位)
const initialX = Phaser.Math.Between(-this.unit * 10, this.screenWidth + this.unit * 10);
targets[0].x = initialX;
targets[0].y = -this.unit * 2;
// 更新动画的x目标值
tween.data[0].value = initialX + horizontalOffset;
}
}
});
}
}
});
}
}
/** /**
* 为开始和退出按钮添加点击功能 * 为开始和退出按钮添加点击功能
*/ */
@@ -480,7 +639,8 @@ export default class MenuScene extends Phaser.Scene {
ease: 'Sine.easeOut', ease: 'Sine.easeOut',
onComplete: (tween, targets) => { onComplete: (tween, targets) => {
// 动画完成后销毁涟漪 // 动画完成后销毁涟漪
if (targets[0] && targets[0].active) { // 确保目标对象仍然存在且未被销毁
if (targets && targets[0] && targets[0].scene && targets[0].active) {
targets[0].destroy(); targets[0].destroy();
} }
} }