iOS设备上Three.js射线投射无响应问题及解决方案
我最近开发了一个带有交互式元素的Three.js场景,里面包含可旋转的门、能打开并触发相机飞行效果的书架书籍,还有可展开播放的视频画布。测试时发现安卓平板和手机上所有交互都正常工作,但iOS设备上完全没有任何交互响应——射线投射逻辑根本不起作用,试了好几种方法都没解决。
后来参考了prisoner849的建议以及编号40541390的解决方案,修改了事件处理代码后问题彻底解决了。核心修改点是针对iOS的触摸事件做适配,把触摸事件转换成鼠标事件的逻辑,让射线投射能正常识别交互。
下面是关键的修改代码:
首先是初始化前的变量声明:
var raycaster; var projector;
然后在init()函数内部添加触摸事件监听:
document.addEventListener('mousedown', onDocumentMouseDown, false); document.addEventListener('touchstart', onDocumentTouchStart, false);
最后实现触摸事件的处理函数,将触摸事件映射到已有的鼠标事件处理逻辑:
function onDocumentTouchStart(event){ event.preventDefault(); event.clientX = event.touches[0].clientX; event.clientY = event.touches[0].clientY; onDocumentMouseDown(event); } function onDocumentMouseDown(event){ projector = new THREE.Projector(); var vector = new THREE.Vector3( ( event.clientX / window.innerWidth ) * 2 - 1, - ( event.clientY / window.innerHeight ) * 2 + 1, 0.5 ); projector.unprojectVector(vector,camera); raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize() ); // 这里是你的相交检测及后续交互逻辑 var intersects = raycaster.intersectObjects( collidableMeshList ); if ( intersects.length > 0 ) { // ... 处理交互的具体代码 } event.preventDefault(); }
原理其实很简单:iOS的触摸事件和桌面端的鼠标事件参数结构不一样,我们通过touchstart事件获取触摸点的坐标,把它赋值给事件对象的clientX和clientY,然后调用原本的onDocumentMouseDown函数,这样射线投射就能基于正确的坐标计算相交对象了。同时调用event.preventDefault()可以避免iOS上的默认触摸行为干扰交互逻辑。
内容的提问来源于stack exchange,提问作者Ivo
相关产品推荐
相关产品推荐

