使用GSAP与Three.js实现灯光颜色随机平滑切换动画的问题
解决GSAP+Three.js灯光颜色无限平滑随机切换问题
问题根源
- 使用
repeat: -1和yoyo: true时,onComplete回调永远不会触发——因为动画会无限重复,没有真正的"完成"状态;onCompleteAll也只会在所有动画(含重复轮次)全部结束时触发,这里无限重复自然不会生效。 change函数里直接赋值camlight3.color = tempColor,会绕过GSAP的过渡逻辑,导致颜色直接跳变,没有平滑效果。
修正方案
放弃repeat和yoyo,改为在每次动画完成后,生成新的随机颜色并启动下一段过渡动画,通过递归调用实现无限循环:
var std = [ new THREE.Color().setHex(0x009dff), new THREE.Color().setHex(0x001aff), new THREE.Color().setHex(0x4000ff), new THREE.Color().setHex(0x7300ff) ]; var camlight3; // 初始化灯光(取消注释并确保this._camera已正确定义) camlight3 = new THREE.PointLight(std[Math.floor(Math.random() * std.length)], 60, 80, 0.0); camlight3.power = 60; camlight3.position.x += 10; camlight3.position.y += 25; camlight3.position.z -= 120; this._camera.add(camlight3); // 启动首次颜色过渡动画 animateToRandomColor(); function animateToRandomColor() { // 生成排除当前颜色的随机索引(可选,避免连续重复同色) let currentIndex = std.findIndex(color => color.equals(camlight3.color)); let randomIndex; do { randomIndex = Math.floor(Math.random() * std.length); } while (randomIndex === currentIndex); const targetColor = std[randomIndex]; // 使用GSAP过渡到目标颜色 gsap.to(camlight3.color, { duration: 2, r: targetColor.r, g: targetColor.g, b: targetColor.b, onComplete: animateToRandomColor // 动画完成后递归调用,实现无限循环 }); }
关键说明
- 递归调用
animateToRandomColor确保每次过渡完成后自动生成新的随机颜色并启动下一段动画,实现无限平滑切换。 - 可选的颜色去重逻辑(do-while循环)避免连续切换到同一种颜色,提升视觉效果;如果不需要可以直接去掉,只保留
randomIndex = Math.floor(Math.random() * std.length)。 - 始终通过GSAP修改
camlight3.color的r/g/b属性,保证过渡效果生效,避免直接赋值导致的跳变。
内容的提问来源于stack exchange,提问作者user3112634
相关产品推荐
相关产品推荐

