Start · Sprachen · JavaScript · Referenz · XRSystem

XRSystem

Schnittstelle

Einstiegspunkt der WebXR Device API: prüft, welche XR-Sitzungsmodi unterstützt werden, und startet über <code>navigator.xr</code> eine <code>XRSession</code> für VR oder AR.

seit JavaScript WebXR Device API – Chromium 79+ (Chrome, Edge, Ope Kategorie: webapi

Signatur

interface XRSystem extends EventTarget

Beschreibung

XRSystem ist die zentrale Schnittstelle der WebXR Device API. Eine eigene Instanz legt man nicht an: Der Browser stellt genau ein Objekt über navigator.xr bereit. Darüber findet eine Webanwendung heraus, ob ein VR-Headset oder AR-fähiges Gerät vorhanden ist, und startet eine immersive oder eingebettete (inline) Sitzung.

Die Schnittstelle hat zwei Methoden:

  • isSessionSupported(mode) – gibt ein Promise<boolean> zurück, das angibt, ob der Modus "inline", "immersive-vr" oder "immersive-ar" grundsätzlich unterstützt wird. Damit lässt sich etwa ein „VR betreten“-Button nur bei vorhandener Hardware einblenden.
  • requestSession(mode, options) – fordert eine XRSession an. Über requiredFeatures und optionalFeatures werden zusätzliche Fähigkeiten verlangt, z. B. "local-floor", "hand-tracking", "hit-test" oder "dom-overlay".

Außerdem ist XRSystem ein EventTarget und löst das Ereignis devicechange aus, wenn XR-Geräte angeschlossen oder getrennt werden. Das kann man über addEventListener("devicechange", …) oder die Eigenschaft ondevicechange abfangen, um die Unterstützung neu zu prüfen.

Üblicher Ablauf: Unterstützung prüfen, nach einer Nutzeraktion (Klick) eine Sitzung anfordern, einen WebGL-Kontext mit xrCompatible: true über XRWebGLLayer anbinden, einen Referenzraum anfordern und die Render-Schleife mit session.requestAnimationFrame() starten.

Parameter

Name Typ Default Beschreibung
$mode Pflicht "inline" | "immersive-vr" | "immersive-ar" Sitzungsmodus für isSessionSupported() und requestSession(). inline rendert in ein Element der Seite, die immersive-*-Modi übernehmen die Anzeige des Geräts.
$options XRSessionInit {} Nur bei requestSession(): Objekt mit requiredFeatures (Array; fehlt eine davon, wird das Promise abgelehnt), optionalFeatures (Array) und je nach Feature weiteren Angaben, z. B. domOverlay: { root: element }.

Rückgabewert

Typ
XRSystem
Beschreibung
Über navigator.xr erreichbar (undefined, wenn der Browser WebXR nicht kennt oder der Kontext nicht sicher ist). isSessionSupported() gibt Promise<boolean> zurück, requestSession() gibt Promise<XRSession> zurück.

Beispiele

Unterstützung prüfen und VR-Button einblenden

const vrButton = document.querySelector('#enter-vr');

const checkXR = async () => {
  if (!('xr' in navigator)) {
    vrButton.textContent = 'WebXR nicht verfügbar';
    vrButton.disabled = true;
    return;
  }
  const supported = await navigator.xr.isSessionSupported('immersive-vr');
  vrButton.disabled = !supported;
  vrButton.textContent = supported ? 'VR betreten' : 'Kein VR-Gerät gefunden';
  console.log('immersive-vr unterstützt:', supported);
};

checkXR();
immersive-vr unterstützt: true

Immersive VR-Sitzung starten und Render-Schleife anbinden

const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl2', { xrCompatible: true });

const startVR = async () => {
  // Muss aus einer Nutzeraktion heraus aufgerufen werden
  const session = await navigator.xr.requestSession('immersive-vr', {
    requiredFeatures: ['local-floor'],
    optionalFeatures: ['hand-tracking']
  });

  session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) });
  const refSpace = await session.requestReferenceSpace('local-floor');

  const onFrame = (time, frame) => {
    const pose = frame.getViewerPose(refSpace);
    if (pose) {
      const layer = session.renderState.baseLayer;
      gl.bindFramebuffer(gl.FRAMEBUFFER, layer.framebuffer);
      gl.clearColor(0.1, 0.1, 0.2, 1);
      gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
      // ... hier pro pose.views zeichnen
    }
    session.requestAnimationFrame(onFrame);
  };
  session.requestAnimationFrame(onFrame);

  session.addEventListener('end', () => console.log('VR-Sitzung beendet'));
};

document.querySelector('#enter-vr').addEventListener('click', () => {
  startVR().catch((err) => console.error('Start fehlgeschlagen:', err.name, err.message));
});

AR-Sitzung mit Hit-Test und DOM-Overlay anfordern

const overlay = document.querySelector('#ar-overlay');

const startAR = async () => {
  if (!(await navigator.xr?.isSessionSupported('immersive-ar'))) {
    console.log('AR wird nicht unterstützt');
    return;
  }
  const session = await navigator.xr.requestSession('immersive-ar', {
    requiredFeatures: ['hit-test'],
    optionalFeatures: ['dom-overlay'],
    domOverlay: { root: overlay }
  });
  console.log('Aktivierte Features:', session.enabledFeatures);
  return session;
};

document.querySelector('#enter-ar').onclick = () => startAR();
Aktivierte Features: ['viewer', 'local', 'hit-test', 'dom-overlay']

Auf angeschlossene oder getrennte Geräte reagieren (devicechange)

const onDeviceChange = async () => {
  const vr = await navigator.xr.isSessionSupported('immersive-vr');
  console.log('Gerätewechsel – VR verfügbar:', vr);
};

navigator.xr?.addEventListener('devicechange', onDeviceChange);

// Später wieder entfernen:
// navigator.xr.removeEventListener('devicechange', onDeviceChange);

// Alternativ über die Handler-Eigenschaft:
// navigator.xr.ondevicechange = onDeviceChange;
Gerätewechsel – VR verfügbar: false

// Wichtig · Fallstricke

  • Nur in sicheren Kontexten: navigator.xr gibt es ausschließlich über HTTPS (oder localhost). In iframes braucht es die Berechtigungsrichtlinie allow="xr-spatial-tracking".
  • Nutzeraktion nötig: requestSession() für immersive Modi wird ohne vorherige Nutzeraktion (z. B. Klick) mit SecurityError abgelehnt. Außerdem ist immer nur eine immersive Sitzung gleichzeitig erlaubt – ein zweiter Versuch führt zu InvalidStateError.
  • Nicht unterstützte Features: Kann eine der requiredFeatures nicht bereitgestellt werden, wird das Promise mit NotSupportedError abgelehnt. Alles, was nicht zwingend nötig ist, gehört deshalb in optionalFeatures. Was tatsächlich aktiv ist, zeigt session.enabledFeatures.
  • isSessionSupported() ist keine Garantie: Ein true heißt nur, dass der Modus grundsätzlich möglich ist. Die Sitzung kann trotzdem scheitern, z. B. wenn der Nutzer die Berechtigung ablehnt.
  • WebGL-Kompatibilität: Der WebGL-Kontext muss mit xrCompatible: true angelegt oder vorher mit await gl.makeXRCompatible() vorbereitet werden, sonst schlägt new XRWebGLLayer() fehl.
  • Browser-Unterstützung: Gut unterstützt in Chromium-Browsern (Chrome/Edge ab 79, Chrome auf Android für AR mit ARCore) und im Meta Quest Browser. Firefox unterstützt WebXR nicht, Safari nur unter visionOS. Immer per Feature-Erkennung ('xr' in navigator) prüfen. Für ältere Umgebungen gibt es das WebXR Polyfill.
  • Datenschutz: Tracking-Daten gelten als sensibel. Browser zeigen daher Einwilligungsdialoge an, besonders bei AR und Hand-Tracking.