fix: 彻底修复GSAP动画泄漏导致的自动转场问题
关键修复: - 在 SceneManager 中保存 animationFrameId 和 introTimeline 引用 - 在 Transition 中保存 timeline 引用 - dispose() 时彻底清理所有 GSAP 动画: * 停止 requestAnimationFrame 循环 * 杀掉开场动画 timeline * 杀掉转场动画 timeline * 杀掉所有针对相机、地球的补间动画 - 添加 Transition.dispose() 方法 - 防止旧动画回调触发导致意外转场 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -30,6 +30,10 @@ export class SceneManager {
|
||||
this.earthModel = null;
|
||||
this.transition = null;
|
||||
|
||||
// 动画控制
|
||||
this.animationFrameId = null;
|
||||
this.introTimeline = null;
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
@@ -97,12 +101,15 @@ export class SceneManager {
|
||||
startIntroSequence(uiElements) {
|
||||
const animConfig = CONFIG.animation.intro;
|
||||
|
||||
const tl = gsap.timeline({
|
||||
// 保存 timeline 引用,以便在 dispose 时清理
|
||||
this.introTimeline = gsap.timeline({
|
||||
onComplete: () => {
|
||||
this.isIntro = false; // 动画结束,允许交互
|
||||
}
|
||||
});
|
||||
|
||||
const tl = this.introTimeline;
|
||||
|
||||
// A. 摄像机缓慢推进 (从 z=100 -> z=16)
|
||||
tl.to(this.camera.position, {
|
||||
z: CONFIG.scene.camera.defaultZ,
|
||||
@@ -279,7 +286,7 @@ export class SceneManager {
|
||||
|
||||
// 动画循环
|
||||
animate() {
|
||||
requestAnimationFrame(() => this.animate());
|
||||
this.animationFrameId = requestAnimationFrame(() => this.animate());
|
||||
|
||||
// 如果不在转场中
|
||||
if (!this.transition || !this.transition.isActive()) {
|
||||
@@ -299,6 +306,31 @@ export class SceneManager {
|
||||
|
||||
// 销毁场景
|
||||
dispose() {
|
||||
// 停止动画循环
|
||||
if (this.animationFrameId) {
|
||||
cancelAnimationFrame(this.animationFrameId);
|
||||
this.animationFrameId = null;
|
||||
}
|
||||
|
||||
// 杀掉所有正在运行的 GSAP 动画
|
||||
if (this.introTimeline) {
|
||||
this.introTimeline.kill();
|
||||
this.introTimeline = null;
|
||||
}
|
||||
|
||||
// 杀掉转场相关的 GSAP 动画(杀掉所有针对相机、地球等对象的动画)
|
||||
if (this.camera) {
|
||||
gsap.killTweensOf(this.camera.position);
|
||||
}
|
||||
if (this.earthModel) {
|
||||
const earthGroup = this.earthModel.getGroup();
|
||||
const clouds = this.earthModel.getClouds();
|
||||
const atmosphere = this.earthModel.getAtmosphere();
|
||||
if (earthGroup) gsap.killTweensOf(earthGroup.rotation);
|
||||
if (clouds) gsap.killTweensOf(clouds.material);
|
||||
if (atmosphere) gsap.killTweensOf(atmosphere.material);
|
||||
}
|
||||
|
||||
// 移除事件监听器,防止内存泄漏和重复触发
|
||||
if (this.eventHandlers) {
|
||||
window.removeEventListener('mousemove', this.eventHandlers.mouseMove);
|
||||
@@ -308,6 +340,12 @@ export class SceneManager {
|
||||
window.removeEventListener('resize', this.eventHandlers.resize);
|
||||
}
|
||||
|
||||
// 清理转场动画
|
||||
if (this.transition) {
|
||||
this.transition.dispose();
|
||||
this.transition = null;
|
||||
}
|
||||
|
||||
if (this.starSystem) this.starSystem.dispose();
|
||||
if (this.earthModel) this.earthModel.dispose();
|
||||
if (this.renderer) {
|
||||
|
||||
@@ -11,6 +11,7 @@ export class Transition {
|
||||
this.uiElements = uiElements; // { uiLayer, hint, speedLines, cloudFog }
|
||||
this.onComplete = onComplete;
|
||||
this.isTransitioning = false;
|
||||
this.timeline = null; // 保存 timeline 引用以便清理
|
||||
}
|
||||
|
||||
// 触发超空间跳跃转场
|
||||
@@ -29,14 +30,16 @@ export class Transition {
|
||||
const clouds = this.earthModel.getClouds();
|
||||
const atmosphere = this.earthModel.getAtmosphere();
|
||||
|
||||
// 创建GSAP时间线
|
||||
const tl = gsap.timeline({
|
||||
// 创建GSAP时间线(保存引用以便清理)
|
||||
this.timeline = gsap.timeline({
|
||||
onComplete: () => {
|
||||
this.isTransitioning = false;
|
||||
if (this.onComplete) this.onComplete();
|
||||
}
|
||||
});
|
||||
|
||||
const tl = this.timeline;
|
||||
|
||||
// 转场配置
|
||||
const warpConfig = CONFIG.warp;
|
||||
const transConfig = CONFIG.animation.transition;
|
||||
@@ -101,4 +104,13 @@ export class Transition {
|
||||
isActive() {
|
||||
return this.isTransitioning;
|
||||
}
|
||||
|
||||
// 清理转场动画
|
||||
dispose() {
|
||||
if (this.timeline) {
|
||||
this.timeline.kill();
|
||||
this.timeline = null;
|
||||
}
|
||||
this.isTransitioning = false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user