Signatur
Beschreibung
XRReferenceSpace ist ein Interface der WebXR Device API. Es erweitert XRSpace und legt fest, wo der Ursprung liegt und wie die Achsen ausgerichtet sind, wenn der Browser Posen (Position und Ausrichtung) des Nutzers oder von Eingabegeräten berechnet. Eine Instanz bekommt man nicht über einen Konstruktor, sondern asynchron über XRSession.requestReferenceSpace(type).
Der Typ des Referenzraums bestimmt, wie sich das Koordinatensystem verhält:
"viewer"– Ursprung am Kopf bzw. Gerät des Nutzers, bewegt sich mit (immer verfügbar)."local"– Ursprung nahe der Startposition des Betrachters, gut für sitzende Erlebnisse."local-floor"– wielocal, aber mit y = 0 auf Bodenhöhe."bounded-floor"– Raum mit festen Grenzen (liefert einXRBoundedReferenceSpacemitboundsGeometry)."unbounded"– für Erlebnisse, bei denen sich der Nutzer frei über große Entfernungen bewegt (z. B. AR im Freien).
Das Interface stellt die Methode getOffsetReferenceSpace(originOffset) bereit, mit der man einen neuen, verschobenen/gedrehten Referenzraum ableitet – typisch für Teleportation oder Drehung per Controller-Stick. Außerdem feuert das Ereignis reset, wenn das System den Ursprung neu festlegt (z. B. nach Tracking-Verlust oder „Neu zentrieren“ durch den Nutzer).
In jeder Frame-Schleife übergibt man den Referenzraum an XRFrame.getViewerPose() oder XRFrame.getPose(), um die aktuellen Posen im gewählten Koordinatensystem zu erhalten.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $originOffset Pflicht | XRRigidTransform | Parameter von getOffsetReferenceSpace(): Transformation (Position + Orientierung), um die der neue Referenzraum gegenüber dem aktuellen verschoben bzw. gedreht wird. |
Beispiele
Referenzraum anfordern und in der Render-Schleife nutzen
const startXR = async () => {
const session = await navigator.xr.requestSession('immersive-vr', {
requiredFeatures: ['local-floor']
});
// Referenzraum mit Boden bei y = 0
const refSpace = await session.requestReferenceSpace('local-floor');
const onFrame = (time, frame) => {
const pose = frame.getViewerPose(refSpace);
if (pose) {
const { x, y, z } = pose.transform.position;
console.log(`Kopfposition: ${x.toFixed(2)}, ${y.toFixed(2)}, ${z.toFixed(2)}`);
}
session.requestAnimationFrame(onFrame);
};
session.requestAnimationFrame(onFrame);
};
document.querySelector('#vr-button').addEventListener('click', startXR);
Fallback, wenn 'local-floor' nicht unterstützt wird
const getRefSpace = async (session) => {
try {
return await session.requestReferenceSpace('local-floor');
} catch (err) {
console.warn('local-floor nicht verfügbar, nutze local:', err.name);
const local = await session.requestReferenceSpace('local');
// Boden grob simulieren: Ursprung 1,6 m nach unten verschieben
return local.getOffsetReferenceSpace(
new XRRigidTransform({ x: 0, y: -1.6, z: 0 })
);
}
};
Teleportation mit getOffsetReferenceSpace()
let refSpace; // wird beim Sessionstart gesetzt
const teleportTo = (target) => {
// Der Welt-Ursprung wird entgegengesetzt verschoben,
// damit der Nutzer an 'target' erscheint
const offset = new XRRigidTransform({ x: -target.x, y: 0, z: -target.z });
refSpace = refSpace.getOffsetReferenceSpace(offset);
};
// Beispiel: 2 m nach vorne teleportieren
teleportTo({ x: 0, z: -2 });
Auf das reset-Ereignis reagieren
const handleReset = (event) => {
console.log('Ursprung wurde zurückgesetzt');
if (event.transform) {
console.log('Versatz zum alten Ursprung:', event.transform.position);
}
// z. B. Szene neu ausrichten oder Teleport-Offset verwerfen
};
refSpace.addEventListener('reset', handleReset);
// Alternativ: refSpace.onreset = handleReset;
// Beim Beenden aufräumen
session.addEventListener('end', () => {
refSpace.removeEventListener('reset', handleReset);
});
// Wichtig · Fallstricke
- Kein Konstruktor:
new XRReferenceSpace()wirft einenTypeError. Instanzen gibt es nur überXRSession.requestReferenceSpace()odergetOffsetReferenceSpace(). - Feature-Anforderung: Außer
viewerund (bei immersiven Sessions)localmüssen Typen wielocal-floor,bounded-flooroderunboundedinrequiredFeatures/optionalFeaturesvonrequestSession()angegeben werden, sonst wird das Promise mitNotSupportedErrorabgelehnt. - Offsets sind unveränderlich:
getOffsetReferenceSpace()ändert den bestehenden Raum nicht, sondern gibt einen neuen zurück – die Referenz im Code muss also ersetzt werden. Offsets addieren sich bei wiederholtem Aufruf. - Pose kann
nullsein: Bei Tracking-Verlust liefertgetViewerPose()null; immer prüfen. - Sicherer Kontext: WebXR funktioniert nur über HTTPS (oder
localhost) und erfordert eine Nutzergeste zum Start einer immersiven Session. Die Permissions-Policyxr-spatial-trackingmuss in iframes erlaubt sein. - Kompatibilität: Unterstützt in Chromium-basierten Browsern (Chrome/Edge 79+ mit passender Hardware, Android-AR), Meta Quest Browser und Samsung Internet. Firefox und Safari auf dem Desktop unterstützen WebXR nicht; Safari auf Apple Vision Pro nur eingeschränkt. Vorher mit
navigator.xr?.isSessionSupported()prüfen.