原生VR模式下屏幕触摸事件未触发,应监听何种事件?
解决Chrome原生VR模式下Cardboard触摸事件无响应的问题
我之前在做AFRAME项目时也碰到过一模一样的问题——Firefox下不管是普通模式还是polyfill VR模式,touchstart都能正常触发,但Chrome原生VR模式里就完全没反应。后来查了WebXR的相关规范才搞明白原因,给你几个可行的解决方案:
核心原因
Chrome的原生VR模式基于WebXR标准,进入沉浸式会话后,浏览器会拦截常规的DOM触摸/鼠标事件,转而通过WebXR专属的输入事件系统来处理交互。Cardboard的触摸按钮在WebXR生态里会触发标准的select事件,而不是原来的touchstart。
方案1:使用AFRAME封装的xrselect事件
AFRAME已经把WebXR的select事件封装成了xrselect,直接绑定到scene上就能监听,代码改动最小,还能兼容原有逻辑:
// 保留原有的touchstart监听(兼容普通模式和Firefox VR) AFRAME.scenes[0].addEventListener('touchstart', function(evt) { if (evt.target.classList.contains('a-enter-vr-button')) { return; } handleInteraction(evt); }); // 新增xrselect监听(兼容Chrome原生VR) AFRAME.scenes[0].addEventListener('xrselect', function(evt) { handleInteraction(evt); }); // 把交互逻辑抽成通用函数,避免重复代码 function handleInteraction(evt) { if (!state.isFlying) { AFRAME.scenes[0].emit('launch', evt); } else { AFRAME.scenes[0].emit('hover', evt); } }
方案2:直接监听WebXR会话的select事件
如果需要更底层的控制,可以在进入VR模式后获取WebXR会话,直接监听它的select事件:
// 监听进入VR的事件,获取XR会话 AFRAME.scenes[0].addEventListener('enter-vr', function() { const xrSession = this.renderer.xr.getSession(); if (xrSession) { xrSession.addEventListener('select', function(evt) { // 这里处理你的交互逻辑 if (!state.isFlying) { AFRAME.scenes[0].emit('launch', evt); } else { AFRAME.scenes[0].emit('hover', evt); } }); } }); // 保留原有的touchstart监听兼容其他场景 AFRAME.scenes[0].addEventListener('touchstart', function(evt) { if (evt.target.classList.contains('a-enter-vr-button')) { return; } if (!state.isFlying) { AFRAME.scenes[0].emit('launch', evt); } else { AFRAME.scenes[0].emit('hover', evt); } });
额外提示
如果你同时使用了其他控制器(比如Oculus手柄),xrselect也会触发它们的主按钮点击,你可以通过evt.inputSource区分Cardboard和其他控制器:
if (evt.inputSource.hand) { // 这是手柄控制器,交给你原有的控制器代码处理 return; } // 处理Cardboard的触摸事件
内容的提问来源于stack exchange,提问作者Doug Reeder
相关产品推荐
相关产品推荐

