Start · Sprachen · JavaScript · Referenz · XRBoundedReferenceSpace

XRBoundedReferenceSpace

Schnittstelle

Beschreibt einen WebXR-Referenzraum vom Typ <code>bounded-floor</code>, dessen begehbare Fläche durch ein Polygon am Boden (<code>boundsGeometry</code>) begrenzt ist.

seit JavaScript WebXR Device API (Chromium 79+, Meta Quest Browser Kategorie: webapi

Signatur

interface XRBoundedReferenceSpace extends XRReferenceSpace

Beschreibung

XRBoundedReferenceSpace erweitert XRReferenceSpace um eine vordefinierte Grenze: Der Nutzer darf sich innerhalb eines bekannten Bereichs frei bewegen, etwa innerhalb der „Guardian“- bzw. „Chaperone“-Zone eines VR-Headsets. Der Ursprung liegt auf Bodenhöhe, die y-Achse zeigt nach oben. Eine Instanz bekommst du ausschließlich über XRSession.requestReferenceSpace('bounded-floor'). Einen öffentlichen Konstruktor gibt es nicht.

Die wichtigste Eigenschaft ist boundsGeometry, ein eingefrorenes Array aus DOMPointReadOnly-Punkten. Die Punkte bilden ein geschlossenes Polygon auf der Bodenebene (y = 0, w = 1) und sind im Uhrzeigersinn angeordnet. Über x und z kannst du die Grenze in der Szene zeichnen, Inhalte innerhalb des erreichbaren Bereichs platzieren oder prüfen, ob sich der Nutzer der Grenze nähert.

Setze diesen Raum für Room-Scale-Erlebnisse ein, bei denen der Nutzer physisch umhergeht, deine Inhalte aber nie außerhalb des sicheren Bereichs liegen sollen. Weil nicht jedes Gerät eine Grenze kennt, fordere das Feature bounded-floor meist nur als optionalFeatures an und weiche auf local-floor aus, falls es fehlt.

Ändert der Nutzer seine Grenze während der Sitzung oder springt das Tracking, löst die Instanz das Ereignis reset aus (geerbt von XRReferenceSpace). Danach kann boundsGeometry neue Werte enthalten und sollte neu ausgelesen werden.

Parameter

Name Typ Default Beschreibung
$boundsGeometry ReadonlyArray<DOMPointReadOnly> Nur lesbare Eigenschaft: Polygonpunkte der Grenze auf der Bodenebene, im Uhrzeigersinn. Ein leeres Array bedeutet, dass die Grenze gerade nicht bekannt ist.
$getOffsetReferenceSpace(originOffset) (XRRigidTransform) => XRBoundedReferenceSpace Geerbte Methode. Bei einem begrenzten Raum ist das Ergebnis wieder ein XRBoundedReferenceSpace, und dessen boundsGeometry ist bereits um den Versatz umgerechnet.
$onreset EventHandler null Geerbter Handler für das Ereignis reset, etwa wenn sich Grenze oder Ursprung ändern. Alternativ: addEventListener('reset', …).

Rückgabewert

Typ
XRBoundedReferenceSpace
Beschreibung
Erhältst du als Auflösungswert des Promise von XRSession.requestReferenceSpace('bounded-floor').

Beispiele

Begrenzten Raum anfordern, mit Ausweichlösung

const startXR = async () => {
  if (!navigator.xr || !(await navigator.xr.isSessionSupported('immersive-vr'))) {
    console.log('WebXR VR nicht verfügbar');
    return;
  }
  // Muss aus einer Nutzergeste heraus aufgerufen werden (z. B. Klick)
  const session = await navigator.xr.requestSession('immersive-vr', {
    optionalFeatures: ['bounded-floor', 'local-floor']
  });

  let refSpace;
  try {
    refSpace = await session.requestReferenceSpace('bounded-floor');
    console.log('Begrenzter Raum aktiv:', refSpace instanceof XRBoundedReferenceSpace);
  } catch {
    refSpace = await session.requestReferenceSpace('local-floor');
    console.log('Ausweichlösung: local-floor');
  }
  return { session, refSpace };
};

document.querySelector('#enter-vr').addEventListener('click', startXR);
Begrenzter Raum aktiv: true

Grenze auslesen und Fläche berechnen

const describeBounds = (refSpace) => {
  const pts = refSpace.boundsGeometry;
  if (pts.length === 0) {
    console.log('Grenze derzeit unbekannt');
    return;
  }
  // Gaußsche Trapezformel auf der x/z-Ebene
  let area = 0;
  pts.forEach((p, i) => {
    const q = pts[(i + 1) % pts.length];
    area += p.x * q.z - q.x * p.z;
  });
  console.log(`Eckpunkte: ${pts.length}, Fläche: ${Math.abs(area / 2).toFixed(2)} m²`);
};

describeBounds(refSpace);
Eckpunkte: 4, Fläche: 6.00 m²

Warnung, wenn der Nutzer den Rand verlässt

// Punkt-in-Polygon-Test mit dem Strahlverfahren
const isInside = (x, z, pts) => {
  let inside = false;
  for (let i = 0, j = pts.length - 1; i < pts.length; j = i++) {
    const a = pts[i], b = pts[j];
    if ((a.z > z) !== (b.z > z) &&
        x < ((b.x - a.x) * (z - a.z)) / (b.z - a.z) + a.x) {
      inside = !inside;
    }
  }
  return inside;
};

const onFrame = (time, frame) => {
  const pose = frame.getViewerPose(refSpace);
  if (pose && refSpace.boundsGeometry.length) {
    const { x, z } = pose.transform.position;
    if (!isInside(x, z, refSpace.boundsGeometry)) {
      console.warn('Achtung: außerhalb der Spielfläche!');
    }
  }
  frame.session.requestAnimationFrame(onFrame);
};
session.requestAnimationFrame(onFrame);
Achtung: außerhalb der Spielfläche!

Auf Änderungen der Grenze reagieren (reset)

const onReset = (event) => {
  console.log('Referenzraum zurückgesetzt, Grenze neu lesen');
  rebuildBoundaryMesh(event.referenceSpace.boundsGeometry);
};

refSpace.addEventListener('reset', onReset);
// alternativ: refSpace.onreset = onReset;

// Beim Beenden der Sitzung wieder abmelden
session.addEventListener('end', () => {
  refSpace.removeEventListener('reset', onReset);
});
Referenzraum zurückgesetzt, Grenze neu lesen

// Wichtig · Fallstricke

  • Browser-Unterstützung: nur in Chromium-Browsern mit WebXR-Hardware (z. B. Chrome/Edge auf dem Desktop mit SteamVR/OpenXR, Meta Quest Browser). Firefox und Safari unterstützen die API derzeit nicht bzw. nur teilweise (visionOS). Sie ist nicht Baseline.
  • Die API erfordert einen sicheren Kontext (HTTPS). Außerdem muss requestSession() aus einer Nutzergeste heraus aufgerufen werden. In iframes braucht es allow="xr-spatial-tracking" (Permissions Policy).
  • 'bounded-floor' muss in requiredFeatures oder optionalFeatures stehen, sonst wird requestReferenceSpace() mit NotSupportedError abgelehnt. Plane immer eine Ausweichlösung auf local-floor ein.
  • boundsGeometry kann ein leeres Array sein, zum Beispiel während der Tracking-Initialisierung. Prüfe die Länge vor der Nutzung.
  • Die Grenze ist absichtlich vereinfacht, damit sich keine Rückschlüsse auf die Wohnung des Nutzers ziehen lassen (Datenschutz). Browser dürfen die Punkte runden oder vergröbern, daher ist sie keine exakte Raumvermessung.
  • Die Grenze ersetzt nicht das System-eigene Sicherheitssystem (Guardian/Chaperone). Verlasse dich für die Sicherheit des Nutzers nicht allein auf eigene Warnungen.