Three.js滚动时使用GSAP实现相机位置平滑动画问题
Three.js滚动触发相机平滑切换位置(GSAP实现)问题排查与解决
以下是针对你遇到的问题的实操性排查点和解决方案:
确认滚动事件绑定正确
把滚动事件绑定到window对象上,避免绑定局部元素导致触发失效,同时不要随意阻止默认滚动行为(除非业务需要):window.addEventListener('scroll', handleScroll);GSAP动画要直接作用于相机position对象
GSAP需要明确操作相机的position属性,并且在动画过程中实时更新相机朝向,否则视角会偏移。示例代码:// 切换到立方体右侧面视角 gsap.to(camera.position, { x: 5, y: 0, z: 0, duration: 1.5, ease: 'power2.inOut', onUpdate: () => { camera.lookAt(0, 0, 0); // 始终看向立方体中心 } });保证渲染循环持续运行
Three.js的渲染必须在requestAnimationFrame循环中持续执行,否则GSAP动画过程中画面不会实时更新:function animate() { requestAnimationFrame(animate); renderer.render(scene, camera); } animate();如果你的渲染逻辑是一次性执行或有条件暂停,动画肯定无法平滑显示。
给滚动触发加节流和阈值判断
滚动事件会连续触发,直接绑定动画会导致动画叠加混乱。可以加一个动画锁和滚动阈值,确保每次只执行一次动画:let isAnimating = false; // 定义对应不同视角的滚动百分比阈值 const viewThresholds = [0, 25, 50, 75, 100]; let currentView = 0; function handleScroll() { if (isAnimating) return; const scrollPercent = (window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100; // 判断当前滚动到哪个视角区间 for (let i = viewThresholds.length - 1; i >= 0; i--) { if (scrollPercent >= viewThresholds[i] && i !== currentView) { currentView = i; switchCameraView(i); break; } } } function switchCameraView(viewIndex) { isAnimating = true; // 定义每个视角对应的相机位置 const targetPositions = [ {x: 0, y: 0, z: 5}, // 正面 {x: 5, y: 0, z: 0}, // 右侧面 {x: 0, y: 0, z: -5}, // 背面 {x: -5, y: 0, z: 0}, // 左侧面 {x: 0, y: 5, z: 0} // 顶面 ]; gsap.to(camera.position, { ...targetPositions[viewIndex], duration: 1.5, ease: 'power2.inOut', onUpdate: () => camera.lookAt(0, 0, 0), onComplete: () => isAnimating = false // 动画结束后解锁 }); }检查GSAP的引入是否正确
确保GSAP脚本在Three.js之后引入,不管是CDN方式还是模块化导入:<!-- CDN引入示例 --> <script src="https://cdn.jsdelivr.net/npm/gsap@3.12.2/dist/gsap.min.js"></script>如果用Vite/Webpack等工具,要正确导入GSAP模块。
内容的提问来源于stack exchange,提问作者Rivera Time Club
相关产品推荐
相关产品推荐

