如何实现上下滚动时Three.js相机仅围绕Y轴旋转?
页面上下滚动控制Three.js相机仅绕Y轴旋转实现方案
以下是纯Vanilla JS环境下可直接落地的实现逻辑:
- 前置配置(如果使用
OrbitControls做基础交互)
先锁死相机绕X轴的俯仰角度,避免交互过程中出现其他维度的旋转偏移:
如果没有引入控件库,直接操作原生相机对象即可,跳过这步。// 锁死垂直方向旋转角度,仅保留水平旋转自由度 controls.minPolarAngle = Math.PI / 2; controls.maxPolarAngle = Math.PI / 2; controls.enableDamping = true; // 开启阻尼优化交互手感 - 滚动事件绑定与角度映射
监听window的scroll事件,将页面滚动进度归一化到0-1区间,再映射为相机Y轴的旋转角度值,不要直接用scrollY原始值计算,避免页面内容高度变化时旋转速度失控:// 全局存储目标旋转角度 let targetYRotation = 0; // 配置旋转总幅度,这里示例为滚动到底部时相机转2整圈 const maxRotation = Math.PI * 4; window.addEventListener('scroll', () => { // 计算页面可滚动的总高度 const maxScrollY = document.documentElement.scrollHeight - window.innerHeight; // 计算当前滚动进度,边界值兜底避免除0 const scrollProgress = maxScrollY > 0 ? window.scrollY / maxScrollY : 0; // 映射为目标旋转角度 targetYRotation = scrollProgress * maxRotation; }, { passive: true }); // 加passive提升滚动性能 - 渲染循环内同步更新相机状态
不要直接在scroll回调中修改相机属性,在requestAnimationFrame驱动的渲染循环中更新状态,保证和渲染帧率同步,还可以方便加缓动效果:function animate() { requestAnimationFrame(animate); // 无缓动:直接赋值 // camera.rotation.y = targetYRotation; // 带缓动效果:插值过渡,数值越小过渡越柔和 camera.rotation.y += (targetYRotation - camera.rotation.y) * 0.1; // 如果使用了OrbitControls记得调用update // controls.update(); renderer.render(scene, camera); } animate(); - 可选优化项
- 如果页面滚动区域和3D画布区域分离,可以单独监听画布对应容器的scroll事件,逻辑和全局监听一致
- 不需要兼容旧浏览器的话,可以用
ScrollTimeline做更丝滑的滚动驱动动画,不需要手动计算进度 - 低性能设备上可以给scroll回调加节流,减少不必要的计算
内容的提问来源于stack exchange,提问作者Cr3
相关产品推荐
相关产品推荐

