0.6.15 • Published 10 months ago

@eyejack/ejx-launcher-button v0.6.15

Weekly downloads
-
License
-
Repository
-
Last release
10 months ago

EJX Launcher Button

This package provides an all-in-one WebXR launcher button that supports all devices, including iOS support for WebXR by running the experience in the EyeJackX App Clip.

Demo: https://demos.eyejack.xyz/index-gallery

Examples

Three.js

import { showThreeLaunchButton } from "@eyejack/ejx-launcher-button";

showThreeLaunchButton({
  // Required
  renderer,

  // (optional) configure and enable VR launcher
  vrOptions: {
    optionalFeatures: [
      "local-floor",
      "bounded-floor",
      "plane-detection",
      "anchors",
    ],
  },
  // (optional) configure and enable AR launcher
  arOptions: {
    optionalFeatures: [
      "local-floor",
      "bounded-floor",
      "plane-detection",
      "anchors",
      "hit-test",
    ],
  },

  // (optional) Reference space for AR, defaults to local.
  arReferenceSpace: "local-floor",
  // (optional) Reference space for VR, defaults to undefined (does not effect renderer.xr)
  vrReferenceSpace: undefined,

  // Occurs after session start.
  // sessionType: 'immersive-ar' | 'immersive-vr'
  onStart: (sessionType) => {
    console.log("Started ", sessionType);
  },
  // Occurs after session end
  onEnd: (sessionType) => {
    console.log("Ended", sessionType);
  },

  // (optional) Root element, for the dom overlay
  container: document.getElementById("my-launcher-root"),
});

Other frameworks

The launcher button can be extended to use other frameworks by implementing the XRSession builder functions. Here's the implementation of showThreeLaunchButton as an example.

:warning: App related side effects (such as showing / hiding elements in your scene) should not be added to xrSessionBuilder or xrSessionEnder but rather onStart and onEnd

import { showLauncherButton } from "@eyejack/ejx-launcher-button";

export const showThreeLaunchButton = ({
  renderer,
  arReferenceSpace = "local",
  vrReferenceSpace,
  ...opts
}: ShowThreeLaunchButtonOptions) => {
  const destroy = showLaunchButton({
    ...opts,
    // Returns a Promise<XRSession>
    xrSessionBuilder: (sessionType) => {
      // Get options for the session type
      const xrOptions = (() => {
        if (sessionType === "immersive-ar" && opts.arOptions) {
          return opts.arOptions;
        } else if (sessionType === "immersive-vr" && opts.vrOptions) {
          return opts.vrOptions;
        }
        throw new Error(
          `@eyejack/ejx-launcher-button: Trying to build xr session with session type ${sessionType}.  This session type is not supported.`
        );
      })();

      // Add dom overlay to close button
      if (!xrOptions.optionalFeatures) {
        xrOptions.optionalFeatures = [];
      }
      if (!xrOptions.optionalFeatures.includes("dom-overlay")) {
        xrOptions.optionalFeatures.push("dom-overlay");
      }
      xrOptions.domOverlay = { root: opts.container ?? document.body };

      // Build the XR Session
      return new Promise((res) => {
        navigator.xr
          ?.requestSession(sessionType, xrOptions)
          .then(async (session) => {
            if (sessionType === "immersive-ar" && arReferenceSpace) {
              renderer.xr.setReferenceSpaceType(arReferenceSpace);
            }
            if (sessionType === "immersive-vr" && vrReferenceSpace) {
              renderer.xr.setReferenceSpaceType(vrReferenceSpace);
            }

            await renderer.xr.setSession(session);
            res(session);
          });
      });
    },
    // Receives the XRSession and ends it.
    xrSessionEnder: (session) => {
      return session.end();
    },
  });
  return destroy;
};

API

The Launcher button will dispatch events to window object and also to the parent window if within an iframe.

:warning: The API has changed to use postMessage instead of dispatchEvent so that it can work with cross origin iframes. This has not been updated in the docs yet.

Example:

  window.addEventListener('message', event => {
    if (event.data.type === '@eyejack/ejx-launcher-button:ready') {
      window.postMessage({
        type: '@eyejack/ejx-launcher-button:start',
        sessionType: 'immersive-ar',
      }, '*');
    }
  });

Exposed functions

window.EJXStartXR

Exposes a global function to start a WebXR session. This is set after @eyejack/ejx-launcher-button:ready.

Returns a Promise<void>

window.addEventListener("@eyejack/ejx-launcher-button:ready", (event) => {
  window.EJXStartXR("immersive-ar").then(() => {
    console.log("Session started.");
  });
});

window.EJXStopXR

Exposes a global function to stop a WebXR session. This is set after @eyejack/ejx-launcher-button:ready.

Returns a Promise<void>

let EJXStopXR;
// Attempts to stop the XR session after 10s
window.addEventListener("@eyejack/ejx-launcher-button:ready", (event) => {
  setTimeout(() => {
    if (window.EJXStopXR) {
      window.EJXStopXR().then(() => {
        console.log("Session started.");
      });;
    }
  }, 10000);
});

Window Action Events

These are events that you can dispatch to interact with the launch button.

:warning: If the WebXR experience is within an iframe you'll need to dispatch These events on document.getElementById('my-iframe').contentWindow;

Example, configuring the iframe to set the launch URL to the parent window url.

const iframe = document.getElementById("my-iframe");
const customEvent = new CustomEvent(
  "@eyejack/ejx-launcher-button:configure",
  {
    detail: {
      launchUrl: window.location.href,
    },
  }
);
iframe.contentWindow.dispatchEvent(customEvent);

@eyejack/ejx-launcher-button:configure

Configures the launcher button

const customEvent = new CustomEvent('@eyejack/ejx-launcher-button:configure', { detail: {
    // Sets the url of the experience to launch
    // @type {string}
    launchUrl: window.location.href

    // Shows or hides the launch button
    showButton: true,
}})
window.dispatchEvent(customEvent)

@eyejack/ejx-launcher-button:start

Starts the WebXR session with a given sesionType

const customEvent = new CustomEvent("@eyejack/ejx-launcher-button:start", {
  detail: {
    // Type of XR Session to start
    sessionType: "immersive-ar",
  },
});
window.dispatchEvent(customEvent);

@eyejack/ejx-launcher-button:stop

Stops the WebXR Session

const customEvent = new CustomEvent("@eyejack/ejx-launcher-button:stop");
window.dispatchEvent(customEvent);

Window Events

These events are dispatched by the launcher button and can be handled to add interactive behaviour in your project.

:information_source: These events will be dispatch to both window and window.parent (if it exists). This means that even if your launcher button is within an iframe, you can still handle these events from the window object of the parent window.

@eyejack/ejx-launcher-button:ready

Triggers when the launcher button has loaded and is ready to start a WebXR session

window.addEventListener("@eyejack/ejx-launcher-button:ready", (event) => {
  // Automatically start XR with a specific session
  const customEvent = new CustomEvent("@eyejack/ejx-launcher-button:start", {
    detail: {
      sessionType: "immersive-ar",
    },
  });
  window.dispatchEvent(customEvent);
});

@eyejack/ejx-launcher-button:started

Triggers after the session has started

window.addEventListener("@eyejack/ejx-launcher-button:started", (event) => {
  console.log("Started ", event.detail.sessionType);
});

@eyejack/ejx-launcher-button:stopped

Triggers after the session has stopped.

window.addEventListener("@eyejack/ejx-launcher-button:stopped", (event) => {
  console.log("Stopped  ", event.detail.sessionType);
});

@eyejack/ejx-launcher-button:redirect

:warning: Required to handle redirects if the experience is viewed within an iframe. This is so the parent window can re-direct to https://play.eyejack.xyz/ and launch the experience in the EyeJackX AppClip.

window.addEventListener("@eyejack/ejx-launcher-button:redirect", (event) => {
  window.location.href = event.detail.launchUrl;
});
0.6.12

10 months ago

0.6.14

10 months ago

0.6.13

10 months ago

0.6.15

10 months ago

0.6.7

12 months ago

0.6.6

12 months ago

0.6.9

12 months ago

0.6.8

12 months ago

0.6.10

11 months ago

0.6.11

11 months ago

0.3.0

1 year ago

0.2.1

1 year ago

0.2.0

1 year ago

0.6.3

12 months ago

0.5.3

12 months ago

0.6.5

12 months ago

0.6.4

12 months ago

0.5.0

12 months ago

0.4.1

12 months ago

0.2.3

1 year ago

0.4.0

1 year ago

0.3.1

1 year ago

0.2.2

1 year ago

0.6.1

12 months ago

0.5.2

12 months ago

0.4.3

12 months ago

0.2.5

1 year ago

0.6.0

12 months ago

0.5.1

12 months ago

0.4.2

12 months ago

0.2.4

1 year ago

0.1.2

1 year ago

0.1.1

1 year ago

0.1.4

1 year ago

0.1.3

1 year ago

0.1.5

1 year ago

0.1.0

1 year ago

0.0.8

1 year ago

0.0.7

1 year ago

0.0.6

1 year ago

0.0.5

1 year ago

0.0.4

1 year ago

0.0.3

1 year ago

0.0.2

1 year ago