Signatur
Beschreibung
Mit requestReferenceSpace() fordert man von einer laufenden XRSession ein Koordinatensystem an. Darin werden die Posen des Betrachters (Kopf) und der Eingabegeräte angegeben. Ohne Referenzraum lassen sich weder XRFrame.getViewerPose() noch XRFrame.getPose() sinnvoll aufrufen. Deshalb gehört der Aufruf fast immer zum Einrichten einer XR-Anwendung, direkt nach navigator.xr.requestSession().
Der gewünschte Typ bestimmt, wo der Ursprung liegt und wie er sich verhält:
"viewer": Der Ursprung folgt dem Kopf des Betrachters. Dieser Typ wird immer unterstützt und eignet sich zum Beispiel für Hit-Tests oder Anzeigen, die am Kopf fixiert sind."local": Der Ursprung liegt fest an der Startposition des Betrachters. Das passt für sitzende Anwendungen. Beiimmersive-*-Sitzungen ist dieser Typ immer verfügbar."local-floor": Wielocal, aber mity = 0auf Bodenhöhe, also für stehende Anwendungen."bounded-floor": Ein begrenzter Spielbereich mit Bodenhöhe. Das Ergebnis ist einXRBoundedReferenceSpacemitboundsGeometry."unbounded": Der Nutzer darf sich frei und weiträumig bewegen, etwa bei AR im Freien.
Alle Typen außer viewer und local müssen beim Start der Sitzung über requiredFeatures oder optionalFeatures angefordert werden. Sonst lehnt das Promise ab. In der Praxis probiert man die Typen der Reihe nach durch, vom gewünschten bis zum sichersten, zum Beispiel erst bounded-floor, dann local-floor, dann local.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $referenceSpaceType Pflicht | "viewer" | "local" | "local-floor" | "bounded-floor" | "unbounded" | Ein String, der den gewünschten Typ des Referenzraums angibt (XRReferenceSpaceType). |
Rückgabewert
"bounded-floor" ist es ein XRBoundedReferenceSpace. Wird der Typ nicht unterstützt, wurde er nicht als Feature angefordert oder ist die Sitzung bereits beendet, lehnt das Promise mit einer NotSupportedError-DOMException ab.Beispiele
Referenzraum anfordern und in der Render-Schleife nutzen
const startXR = async () => {
const session = await navigator.xr.requestSession('immersive-vr', {
optionalFeatures: ['local-floor']
});
const refSpace = await session.requestReferenceSpace('local-floor');
const onFrame = (time, frame) => {
session.requestAnimationFrame(onFrame);
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);
};
document.querySelector('#vr-button').addEventListener('click', startXR);
Mehrere Typen der Reihe nach durchprobieren
const getBestReferenceSpace = async (session) => {
const types = ['bounded-floor', 'local-floor', 'local'];
for (const type of types) {
try {
const space = await session.requestReferenceSpace(type);
console.log(`Verwende Referenzraum: ${type}`);
return { type, space };
} catch (err) {
console.warn(`${type} nicht verfügbar:`, err.name);
}
}
throw new Error('Kein passender Referenzraum verfügbar');
};
const session = await navigator.xr.requestSession('immersive-vr', {
optionalFeatures: ['bounded-floor', 'local-floor']
});
const { type, space } = await getBestReferenceSpace(session);
Grenzen des Spielbereichs auslesen (bounded-floor)
const session = await navigator.xr.requestSession('immersive-vr', {
requiredFeatures: ['bounded-floor']
});
const bounded = await session.requestReferenceSpace('bounded-floor');
// boundsGeometry: Array von DOMPointReadOnly auf Bodenhöhe (y = 0)
const punkte = bounded.boundsGeometry.map(({ x, z }) => `(${x.toFixed(1)}, ${z.toFixed(1)})`);
console.log('Spielbereich:', punkte.join(' → '));
Viewer-Raum für AR-Hit-Tests
const session = await navigator.xr.requestSession('immersive-ar', {
requiredFeatures: ['hit-test', 'local']
});
const viewerSpace = await session.requestReferenceSpace('viewer');
const localSpace = await session.requestReferenceSpace('local');
// Strahl geht vom Gerät (Viewer) aus, Treffer werden relativ zu local ausgewertet
const hitTestSource = await session.requestHitTestSource({ space: viewerSpace });
session.requestAnimationFrame(function onFrame(t, frame) {
session.requestAnimationFrame(onFrame);
const [hit] = frame.getHitTestResults(hitTestSource);
if (hit) console.log('Treffer:', hit.getPose(localSpace).transform.position);
});
// Wichtig · Fallstricke
- Feature anfordern:
local-floor,bounded-floorundunboundedmüssen beirequestSession()inrequiredFeaturesoderoptionalFeaturesstehen. Fehlen sie dort, lehnt das Promise mitNotSupportedErrorab, auch wenn die Hardware den Typ könnte. - Inline-Sitzungen: Bei
"inline"ist ohne weitere Features nurviewergarantiert. - Tracking-Verlust: Der Ursprung kann sich verschieben, etwa bei Neukalibrierung oder einem Wechsel des Spielbereichs. Dann feuert das Ereignis
resetamXRReferenceSpace. Beibounded-floorsollte man danachboundsGeometryneu auslesen. - Versatz: Mit
getOffsetReferenceSpace()lässt sich ein vorhandener Raum verschieben oder drehen, zum Beispiel zum Teleportieren. Ein neuerrequestReferenceSpace()-Aufruf ist dafür nicht nötig. - Kompatibilität: WebXR funktioniert nur in sicheren Kontexten (HTTPS) und kann per Permissions Policy (
xr-spatial-tracking) gesperrt sein. Unterstützt wird es vor allem in Chromium-Browsern und im Meta Quest Browser. Firefox und Desktop-Safari unterstützen es nicht, Safari auf der Apple Vision Pro nur teilweise. - Auf einer beendeten Sitzung lehnt das Promise mit
InvalidStateErrorab.