Three.js移动端触摸Body滚动受阻及旋转场景后滚动失效解决方案咨询
这个问题我之前在移动端做Three.js项目时也碰到过,核心原因是Three.js的交互控制器(比如OrbitControls)会默认捕获并阻止触摸事件的冒泡/默认行为,导致页面的滚动事件被“吃掉”了,尤其是在完成旋转操作后,控制器没有正确释放对触摸事件的控制权。
一、核心解决办法:调整触摸事件的处理逻辑
最直接的方案是修改OrbitControls的配置或事件监听,让它只在需要处理旋转时才拦截触摸事件,其余时候允许页面滚动:
方案1:用CSS
touch-action明确触摸行为
给canvas元素添加CSS属性,告诉浏览器哪些触摸动作由它处理,哪些交给Three.js:canvas { touch-action: pan-y; /* 允许垂直方向的页面滚动,旋转/缩放等动作交给Three.js处理 */ }这个方法最简单有效,它能让浏览器和Three.js各司其职,不会互相干扰触摸事件。
方案2:精细配置OrbitControls的触摸规则
如果你用的是OrbitControls,可以调整触摸触发逻辑,比如限制只有双指操作时才处理旋转,单指操作允许页面滚动:controls.touches = { ONE: THREE.TOUCH.NONE, // 单指不触发旋转,让页面可以滚动 TWO: THREE.TOUCH.DOLLY_ROTATE // 双指处理旋转和缩放 }; controls.enableDamping = true; // 优化旋转的顺滑度
二、关于canvas上方叠加div的问题
是否可行?
叠加div是完全可行的,但这个操作本身不能直接解决滚动卡住的问题——因为核心矛盾是Three.js控制器对触摸事件的拦截,不是上层元素的遮挡。不过如果是为了做UI层(比如按钮、标题),这个方案非常实用。叠加后还能旋转场景吗?
当然可以!只要给叠加的div设置pointer-events: none,触摸事件就会完全穿透到下方的canvas,Three.js的控制器依然能正常接收到触摸信号来处理旋转。如果叠加的div里有需要交互的UI元素,只给这些元素单独设置pointer-events: auto即可,不会影响整体交互。
内容的提问来源于stack exchange,提问作者user3112634

