jeromeetienne / AR.js

Efficient Augmented Reality for the Web - 60fps on mobile!
MIT License
15.8k stars 2.22k forks source link

Unable to start on React #622

Closed ghost closed 5 years ago

ghost commented 5 years ago

Describe the bug I'm trying to use ARjs inside a NextJS application, with the help of aframe-react dependency. When launching it on browser, I get this exception on console:

Uncaught Error: The component arjs-anchor has been already registered. Check that you are not loading two versions of the same component or two different components of the same name. at Object.module.exports.registerComponent (aframe-master.js:73904) at aframe-ar.js:8249 Apparently on the page only A-Frame starts and I'm unable to see my camera. This is my current implementation:

The Page component - My webpage

// Main
const Resume = ({origin, pathname}) => {
  [...]
  return (
    <>
      {pages.map((page) => ( // It maps a GraphQL query - not important
        <Head key={page.id}>
          <title>{lang === 'it' ? page.data.title.en : page.data.title.en}</title>
          <meta name="og:url" property="og:url" content={origin + pathname} />
          <meta name="og:title" property="og:title" content={lang === 'it' ? page.data.title.en : page.data.title.en} />
          <meta name="robots" content="noindex,nofollow" />
          {/* Preload Start */}
          <link rel="preload" href="/static/js/lib/arjs/aframe-ar.js" as="script" />
          {/* Preload End */}
          {/* JS Imports Start */}
          // Here I'm importing AR because I'm not allowed inside Stage, due to its not-module nature
         // I tried to import aframe here too, but I'm getting more exceptions in doing it
          <script src="/static/js/lib/arjs/aframe-ar.js"></script>
          {/* JS Imports End */}
        </Head>
      ))}
      {pages.map((page) => (
       // The actual component that contains aframe
        <Stage key={page.id} />
      ))}
    </>
  );
}

Stage - The component that contains aframe/AR

// Module Start
// JS imports
import React from 'react'
import {Entity, Scene} from 'aframe-react'

/**
 * @description Stage Class
 * @author Luca Cattide
 * @date 2019-08-05
 * @class Stage
 * @extends {React.Component}
 */
class Stage extends React.Component {
  /**
   * Creates an instance of Stage
   * @author Luca Cattide
   * @date 2019-08-05
   * @param {object} props Properties
   * @memberof Stage
   */
  constructor(props) {
    super(props);

    this.state = {
      appRendered: false,
    };
  }

  /**
   * @description Mounted component cycle
   * @author Luca Cattide
   * @date 2019-08-05
   * @memberof Stage
   */
  componentDidMount() {
    const stage = this;
    const stageContainer = $('#stage__container');

    if (typeof window !== 'undefined') {
     // I'm initializing here aframe following aframe-react instructions
      require('aframe');
      require('aframe-look-at-component');

     I've tried to include here ARjs with no success

      // State management
      stage.setState({
        appRendered: true
      });
      // UX
      stageContainer.removeClass('occult');
    }
  }

  /**
   * @description Stage rendering
   * @author Luca Cattide
   * @date 2019-08-05
   * @returns
   * @memberof Stage
   */
  render() {
    return (
      // Stage Start
      <div id="stage__container" className="occult">
        {this.state.appRendered &&
          // TODO: Remove inspector in production
          <Scene embedded keyboard-shortcuts arjs="sourceType: webcam; debugUIEnabled: false;" inspector="https://cdn.jsdelivr.net/gh/aframevr/aframe-inspector@master/dist/aframe-inspector.min.js">
            {/* Marker Start */}
            <Entity primitive="a-marker" preset="hiro">
              <Entity gltf-model="url(/static/3d/hello-my-friends-parsakaita-cc.gltf)" data-cc="Hello my friends by Parsakaita - Creative Commons — Attribution NonCommercial 4.0 International — CC BY-NC 4.0" look-at="#camera" />
            </Entity>
            {/* Marker End */}
            {/* Camera Start */}
            <Entity id="rig" position="0 0 0">
              <Entity id="camera" primitive='a-camera' wasd-controls />
            </Entity>
            {/* Camera End */}
          </Scene>
        }
      </div>
      // Stage End
    );
  }
}

// Module export
export default Stage
// Module End

To Reproduce Steps to reproduce the behavior:

  1. Go to http://lucacattide.dev/resume
  2. Inspect page
  3. See error

Expected behavior The page should correctly render the component with AR library too, then the user should be able to read markers as expected

Screenshots Screenshot 2019-10-22 at 16 30 14 Screenshot 2019-10-22 at 16 30 28

Desktop (please complete the following information):

Additional context I think that could be related to ARjs library inclusion, but I'm a bit confused about how to render it correctly in conjunction with this scenario resources.

Thanks in advance for the help.

nicolocarpignoli commented 5 years ago

Hi, i'm guessing the error of multiple imports occurs because of

         {/* Preload Start */}
          <link rel="preload" href="/static/js/lib/arjs/aframe-ar.js" as="script" />
          {/* Preload End */}
          {/* JS Imports Start */}
          // Here I'm importing AR because I'm not allowed inside Stage, due to its not-module nature
         // I tried to import aframe here too, but I'm getting more exceptions in doing it
          <script src="/static/js/lib/arjs/aframe-ar.js"></script>

those link and script tags that are referencing the same files. Try to remove one.

For AR.js on React, in general, did you already checked other similar issues on this repository? This topic has been quite popular recently, you may find something useful.

ghost commented 5 years ago

Hi Nicolò, thanks for replying. Yes, I was reading the #493 specifically, but the tips suggested in this issue doesn't fit in my case. I tried with your suggestion, but unfortunately deleting only a script preload wasn't enough to solve it.

EDIT:

Just noticed that sometimes the camera starts, but blank screen stills. I'm sure it's all related to script initialisation, but as I said, I'm stuck now about its integration inside my current setting.

EDIT 2:

For now I solved by falling back on usual plain HTML. Hope in the future this awesome library will be available for JS frameworks too, in a stable version.

Thanks for your help.