Я продолжаю видеть «Не удалось выполнить» Сеанс запросов » в «XRSystem»: уже есть активная, захватывающая XRSession», когда я пытаюсь использовать WebXR в React

#javascript #reactjs #three.js #augmented-reality #webxr

Вопрос:

Кому-нибудь удалось успешно использовать WebXR в React? Я пытаюсь преобразовать код в следующем руководстве из vanilla.js чтобы react.js :

https://www.devbridge.com/articles/ar-app-development-tutorial/

Но я продолжаю видеть ошибку, говорящую:

 Uncaught (in promise) DOMException: Failed to execute 'requestSession' on 'XRSystem': There is already an active, immersive XRSession.
 

У меня нет проблем с использованием кода в vanilla.js.

Моя версия кода React такова:

 import React, {useState} from 'react'

const AR = () => {

  const [xrButton, setXRButton] = useState('XR Not Found')
  const [info, setInfo] = useState('')

  //check if XR is supported or not
  const [supported, setSupported] = useState(false)

  const [check, setCheck] = useState(false)

  const { XRWebGLLayer } = window


  // to control the xr session
  let xrSession = null 

  // reference space used within an application
  let xrRefSpace = null 

  // Canvas OpenGL context used for rendering
  let gl = null 

  //Check if there are any WebXR errors in Window
  const checkXR = () => {

    if(!check){
      if (!window.isSecureContext) {
        document.getElementById("warning").innerText = "WebXR unavailable. Please use secure context" 
      }
      if (navigator.xr) { // check to see if WebXR is supported
        navigator.xr.addEventListener('devicechange', checkSupportedState) 
        checkSupportedState() 
      } else {
        document.getElementById("warning").innerText = "WebXR unavailable for this browser" 
      }
      setCheck(true)
    }
    
  }

  //check if webxr is supported
  const checkSupportedState = () => {
   
    if(navigator.xr){
      navigator.xr.isSessionSupported('immersive-ar').then((isSupported) => {
        setSupported(isSupported)
        if (isSupported) {
          setXRButton('View in AR')
          console.log("supported:", isSupported)
        } else {
          setXRButton('AR not found')
          console.log("WebXR doesn't support immersive-ar mode!") 
        }
        
      }) 
    }
    else {
      console.log("WebXR is not available!")
    }
  }

  //if webxr is supported, allow onButtonClicked handler to be called
  const onButtonClicked = () => {
    if (!xrSession) {
        navigator.xr.requestSession('immersive-ar', {
            optionalFeatures: ['dom-overlay'],
            requiredFeatures: ['local'],
            domOverlay: {root: document.getElementById('overlay')}
        }).then((session) => {
          xrSession = session
          setXRButton('Exit AR')
          onSessionStarted(xrSession)
        })
    } else {
      xrSession.end().then(() => xrSession = null)
    }
  }

  //when immersive-ar session starts
  const onSessionStarted = (session) =>{

    // Show which type of DOM Overlay got enabled (if any)
    if (session.domOverlayState) {
     setInfo('DOM Overlay type: '   session.domOverlayState.type)
    }

    session.addEventListener('end', onSessionEnded);

    // create a canvas element and WebGL context for rendering
    let canvas = document.createElement('canvas');
    gl = canvas.getContext('webgl', { xrCompatible: true });
    session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) });

    session.requestReferenceSpace('local').then((refSpace) => {
      xrRefSpace = refSpace;
      // start WebXR rendering loop
      session.requestAnimationFrame(onXRFrame);
    });

  }

  //once immersive-ar session ends
  const onSessionEnded = (event) => {
      xrSession = null;
      setXRButton( 'Enter AR')
      setInfo('')
      gl = null;
  }

  //on the frame once session starts
  const onXRFrame = (t, frame) => {
    let session = frame.session;
    session.requestAnimationFrame(onXRFrame);
    let pose = frame.getViewerPose(xrRefSpace);
    if (!pose) {
      return;
    }
    const pos = pose.transform.position;
    setInfo(`x:${pos.x.toFixed(2)}m y:${pos.y.toFixed(2)}m z:${pos.z.toFixed(2)}m`)
  }

  //call checkXR function
  checkXR()





  return (
    <div id="overlay">
      <div className="info-area">
        <div id="info">{info}</div>
        { supported ?
          <button id="xr-button" onClick={onButtonClicked}>{xrButton}</button>
            :
              <button id="xr-button" disabled>{xrButton}</button>

        }
        
      </div>
    </div>
  ) 
}

export default AR 
 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
 

Я не уверен, что делаю что-то не так. Я еще не реализовал ни одного из Three.js элементов на экране еще нет. Я пытаюсь проверить, начнется ли сеанс погружения в ar или нет, но у меня возникли проблемы с этим. Те же шаги последовали и в vanilla.js не столкнулся ни с какими проблемами.