如何在WebVR / A-Frame中收听Android Chrome上的点击事件?

时间:2018-03-05 03:29:22

标签: javascript android google-chrome aframe webvr

我正在尝试在Android Chrome上收听点击事件(确切地说,从谷歌纸板中拉出磁铁),但如果设备进入VR模式,这似乎无效。我正在使用三星Galaxy S7进行测试:

JS:

window.addEventListener('click', function (evt) {
    console.log("test")
});

在Samsung内置的Android浏览器中,日志可以在VR模式内外打印。在Android Chrome中,只有在浏览器未处于VR模式时才会显示日志记录。

HTML:

<a-entity camera="userHeight: 1.6" restrict-position look-controls>
    <a-entity cursor="fuse: true; fuseTimeout: 500"
                position="0 0 -1"
                geometry="primitive: ring; radiusInner: 0.02; radiusOuter: 0.03"
                material="color: black; shader: flat">
    </a-entity>
</a-entity>

我正在使用A-Frame ver 0.7.0,但这个问题也可以通过使用本机WebVR API重现。

我认为画布可能正在消耗点击事件,所以我尝试将eventlistener直接添加到Canvas。这也行不通。

这是Chrome中的错误吗?有没有解决方法?我只需要能够听按钮按下。

2 个答案:

答案 0 :(得分:2)

我终于找到了一种有效的方法。我们必须使用本机WebVR API:

function addVRClickListener(clickCallback) {
    let lastButtonState = [];
    let presentingDisplay = null;

    // Set up a loop to check gamepad state while any VRDisplay is presenting.
    function onClickListenerFrame() {
      // Only reschedule the loop if a display is still presenting.
      if (presentingDisplay && presentingDisplay.isPresenting) {
        presentingDisplay.requestAnimationFrame(onClickListenerFrame);
      }

      let gamepads = navigator.getGamepads();
      for (let i = 0; i < gamepads.length; ++i) {
        let gamepad = gamepads[i];
        // Ensure the gamepad is valid and has buttons.
        if (gamepad &&
            gamepad.buttons.length) {
          let lastState = lastButtonState[i] || false;
          let newState = gamepad.buttons[0].pressed;
          // If the primary button state has changed from not pressed to pressed 
          // over the last frame then fire the callback.
          if (newState && !lastState) {
            clickCallback(gamepad);
          }
          lastButtonState[i] = newState;
        }
      }
    }

    window.addEventListener('vrdisplaypresentchange', (event) => {
      // When using the polyfill, CustomEvents require event properties to
      // be attached to the `detail` property; native implementations
      // are able to attach `display` directly on the event.
      var display = event.detail ? event.detail.display : event.display;
      if (display.isPresenting) {
        let scheduleFrame = !presentingDisplay;
        presentingDisplay = display;
        if (scheduleFrame)
          onClickListenerFrame();
      } else if (presentingDisplay == display) {
        presentingDisplay = null;
      }
    });
  }

  return {
    isMobile: isMobile,
    addError: addError,
    addInfo: addInfo,
    addButton: addButton,
    removeButton: removeButton,
    makeToast: makeToast,
    addVRClickListener: addVRClickListener
  };
})();

然后我们可以注册点击:

  addVRClickListener(onClick);

我在A-frame的代码中看到的问题是,它没有考虑传播触摸事件的显示更改(非vr - > vr)。

这似乎是A-Frame中的一个错误。

答案 1 :(得分:1)

这听起来与我在磁性按钮上看到的一些问题有关。

首先要尝试的是touchstart而不是click:

您可以尝试将此组件添加到场景中,看看它是否有效:

<script>
AFRAME.registerComponent("click-handler", {
    init: function() {
        const sceneEl = this.el.sceneEl
        const canvasEl = sceneEl.canvas    
        canvasEl.addEventListener('touchstart', () => {
            // code here
        })
    }
});
</script>

<a-scene click-handler>...</a-scene>

此主题中的更多上下文: aframe cardboard button (magnet) click does not trigger

接下来,如果这不起作用,那么chrome标志和这个线程可能会有所帮助:

Detect Google Cardboard Magnetic Button Click in Javascript

铬://标志/#启用泛型传感器

铬://标志/#启用泛型传感器的额外的类