How to add html dom-overlay on top of the WebXR in react

135 views Asked by At

im working on a school project and having some trouble with react and webXR. I never used react and webXR so this is a new experience for me. I am trying to add two buttons that can be overlayed on top of the XR scene, and each have functionality. One would redirect the user back and one would open a pop up menu.

For some reason when I add onClick and just a simple console log to the button, nothing happens. Please advise.

ARView.jsx

import { Html, OrbitControls } from "@react-three/drei";
import { useThree } from "@react-three/fiber";
import { Interactive, useHitTest, useXR } from "@react-three/xr";
import { useRef, useState } from "react";
import Cube from "./Cube";
import './ARView.css';
import { FaArrowAltCircleLeft, FaInfoCircle } from 'react-icons/fa';

const ARView = () => {

    const reticleRef = useRef();
    const [cubes, setCubes] = useState([]);
    const { isPresenting } = useXR();

    useThree(({ camera }) => {
        if (!isPresenting) {
            camera.position.z = 3;
        }
    });

    useHitTest((hitMatrix, hit) => {
        hitMatrix.decompose(
            reticleRef.current.position,
            reticleRef.current.quaternion,
            reticleRef.current.scale
        );

        reticleRef.current.rotation.set(-Math.PI / 2, 0, 0);
    });

    const placeCube = (e) => {
        let position = e.intersection.object.position.clone();
        let id = Date.now();
        setCubes([...cubes, { position, id }]);
    };

    return (
        <>
            <OrbitControls />
            <ambientLight />
            {isPresenting &&
                cubes.map(({ position, id }) => {
                    return <Cube key={id} position={position} />;
                })}
            {isPresenting && (
                <Interactive onSelect={placeCube}>
                    <mesh ref={reticleRef} rotation-x={-Math.PI / 2}>
                        <ringGeometry args={[0.1, 0.25, 32]} />
                        <meshStandardMaterial color={"white"} />
                    </mesh>
                </Interactive>
            )}
            {isPresenting && (
                <Html>
                    <div className="nav-container">
                        <button className="nav-button"><FaArrowAltCircleLeft /></button>
                        <button className="nav-button"><FaInfoCircle /></button>
                    </div>
                </Html>
            )}

            {!isPresenting && <Cube />}
        </>
    );
};

export default ARView;

ARViewContainer.jsx

import { Canvas } from "@react-three/fiber";
import { ARButton, XR } from "@react-three/xr";
import ARView from "./ARView";

const ARViewContainer = () => {
return (
    <>
    <ARButton
        sessionInit={{
        requiredFeatures: ["hit-test"],
        }}
    />
    <Canvas>
        <XR>
        <ARView />
        </XR>
    </Canvas>
    </>
);
};

export default ARViewContainer;

after that it is just imported into the App.jsx

1

There are 1 answers

0
timhc22 On

You can do like this:

      <XRButton
        mode={'AR'}
        sessionInit={{
          optionalFeatures: [
            "dom-overlay",
          ],
          domOverlay: { root: document.body }
        }}

If you can figure out how to change the 'root' to something like document.body.querySelector(".xrOverlay") I'd be interested to know.