<div class="help">
  <img src="https://stemkoski.github.io/AR-Examples/markers/hiro.png">
</div>
<script>
  if (typeof AFRAME === 'undefined') {
    throw 'Component attempted to register before AFRAME was available.';
  }
  AFRAME.registerComponent('axes-helper', {
    schema: {
      size: {
        type: 'number',
        default: 5
      }
    },
    init: function() {
      var data = this.data;
      this.axes = new THREE.AxesHelper(data.size);
      this.el.setObject3D('axes-helper', this.axes);
    }
  });
</script>
<a-scene embedded arjs>
  <a-marker preset="hiro">
    <a-box depth=".5" height=".5" width="0.5" color="tomato" opacity="0.5" transparent="true"></a-box>
    <a-entity axes-helper></a-entity>
  </a-marker>
  <a-entity camera></a-entity>
</a-scene>
body
  margin: 0
  height: 100vh
  width: 100vw
  // overflow: hidden
  
.help
  // position: fixed
  z-index: 999999
  // right: 0
  top: 0
  img
    height: 250px
    width: auto
View Compiled
import * as THREE from "https://cdn.skypack.dev/three";
import { OrbitControls } from "https://cdn.skypack.dev/three/examples/jsm/controls/OrbitControls";

class WebglEngine {
  public renderer: THREE.WebGLRenderer;
  public camera: THREE.PerspectiveCamera;
  public scene: THREE.Scene;
  public controls: OrbitControls;
  public cb: Function = () => {};
  public ac = document.querySelector('.a-canvas') as HTMLElement;

  constructor() {
    this.renderer = new THREE.WebGLRenderer({
      antialias: true,
      alpha: true
    });
    this.renderer.setSize(innerWidth, innerHeight);
    this.renderer.outputEncoding = THREE.sRGBEncoding;
    document.body.appendChild(this.renderer.domElement);
    this.renderer.domElement.style.cssText = `
      position: absolute;
      z-index: 999;
      left: 0;
      top: 0;`;
    this.camera = new THREE.PerspectiveCamera(80, 1, 0.005, 10000);
    this.scene = new THREE.Scene();
    this.controls = new OrbitControls(this.camera, this.renderer.domElement);
    this.onWindowResize();
    window.addEventListener("resize", this.onWindowResize, false);
  }

  public onWindowResize = () => {
    this.camera.aspect = this.ac.offsetWidth / this.ac.offsetHeight;
    this.renderer.setSize(this.ac.offsetWidth, this.ac.offsetHeight);
    this.camera.updateProjectionMatrix();
    this.renderer.domElement.style.top = `${document.body.style.marginTop}`;
    this.renderer.domElement.style.left = `${document.body.style.marginLeft}`;
  };

  private render() {
    this.cb();
    this.renderer.render(this.scene, this.camera);
    requestAnimationFrame(() => this.render());
  }

  public animate(cb: Function) {
    this.cb = cb;
    this.render();
  }
}

const engine = new WebglEngine();

const mesh = new THREE.Mesh(
  new THREE.BoxGeometry(1, 1, 1, 1),
  new THREE.MeshNormalMaterial({ transparent: true, opacity: 0.75 })
);
mesh.matrixAutoUpdate = true;
mesh.matrixWorldNeedsUpdate = true;

const helper = new THREE.AxesHelper(5);
helper.matrixAutoUpdate = true;
helper.matrixWorldNeedsUpdate = true;

const group = new THREE.Group();
group.add(mesh, helper);
group.visible = false;
group.matrixAutoUpdate = true;
group.matrixWorldNeedsUpdate = true;

engine.camera.position.set(0, 0, 0);
engine.camera.matrixAutoUpdate = true;
engine.camera.matrixWorldNeedsUpdate = true;

engine.scene.add(group);
engine.animate(() => {});

const initARJS = async () => {
  const camera = document.querySelector("[camera]") as any;
  const marker = document.querySelector("a-marker") as any;
  const scene = document.querySelector("a-scene") as any;
  
  const helpm = document.querySelector('.help') as HTMLelement;
  helpm.style.right = '0';
  helpm.style.top = '0';
  helpm.style.position = 'fixed';
  
  const propsToCopy = [
    "matrix",
    "matrixWorld",
    "normalMatrix",
    "modelViewMatrix",
    "position",
    "rotation",
    "quaternion",
    "scale"
  ];
  const copyProps = (
    to: THREE.Object3D | any,
    from: THREE.Object3D,
    props: string[] = propsToCopy
  ) => {
    props.forEach((prop) => {
      //@ts-ignore
      to[prop].copy(from[prop]);
    });
  };

  marker.addEventListener("markerLost", () => {
    group.visible = false;
    engine.cb = () => {};
  });

  marker.addEventListener("markerFound", () => {
    group.visible = true;
    const camera = document.querySelector("[camera]") as any;
    const marker = document.querySelector("a-marker") as any;
    engine.cb = () => {
      const box = document.querySelector("a-box") as any;

      copyProps(group, marker.object3D, ["matrix"]);
      group.updateMatrix();
      group.updateMatrixWorld();
      group.position.setFromMatrixPosition(marker.object3D.matrix);
      group.rotation.setFromRotationMatrix(marker.object3D.matrix);
      group.quaternion.setFromRotationMatrix(marker.object3D.matrix);
      group.scale.setFromMatrixScale(marker.object3D.matrix);
      group.updateMatrix();
      group.updateMatrixWorld();

      copyProps(mesh, box.object3D, ["modelViewMatrix", "matrix"]);
      mesh.updateMatrix();
      mesh.updateMatrixWorld();

      copyProps(engine.camera, camera.object3D, [
        "matrix",
        "matrixWorld",
        "normalMatrix",
        "modelViewMatrix"
      ]);
      engine.camera.updateMatrix();
      engine.camera.updateMatrixWorld();
      engine.camera.updateProjectionMatrix();
      engine.camera.position.setFromMatrixPosition(camera.object3D.matrix);
      engine.camera.rotation.setFromRotationMatrix(camera.object3D.matrix);
      engine.camera.quaternion.setFromRotationMatrix(camera.object3D.matrix);
      engine.camera.scale.setFromMatrixScale(camera.object3D.matrix);
      engine.camera.updateMatrix();
      engine.camera.updateMatrixWorld();
      engine.camera.updateProjectionMatrix();

      // console.log('marker', marker.object3D);
      // console.log('threej', group);
      // console.log('marker-child', marker.object3D.children[0]);
      // console.log('threej-child', group.children[0]);
    };
  });
};

initARJS();
View Compiled
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.