Signatur
Beschreibung
Die Schnittstelle XRAnchor gehört zum WebXR Anchors Module. Ein Anker ist ein Punkt im Raum, den das XR-System fest mit der realen Umgebung verbindet. Während sich das Verständnis der Umgebung verbessert (z. B. durch SLAM-Korrekturen), passt das Gerät die Pose des Ankers laufend an. Virtuelle Objekte, die an einem Anker hängen, bleiben dadurch an derselben Stelle in der echten Welt, statt mit der Zeit wegzudriften.
Anker werden nicht über einen Konstruktor erzeugt. Man legt sie asynchron an, entweder mit XRFrame.createAnchor(pose, space) an einer beliebigen Pose oder mit XRHitTestResult.createAnchor() an einer erkannten Oberfläche. Beide Methoden geben ein Promise<XRAnchor> zurück. Die Session muss dafür mit dem Feature "anchors" angefordert werden.
Die Schnittstelle hat folgende Mitglieder:
anchorSpace(schreibgeschützt): einXRSpace, mit dem man in jedem Frame perframe.getPose(anchor.anchorSpace, refSpace)die aktuelle Pose abfragt.delete(): gibt den Anker frei. Danach verfolgt das System ihn nicht mehr.requestPersistentHandle()(experimentell, nur Meta Quest Browser): gibt einPromise<string>mit einer UUID zurück. Damit lässt sich der Anker in einer späteren Session überXRSession.restorePersistentAnchor()wiederherstellen.
Alle Anker, die in einem Frame verfolgt werden, liefert XRFrame.trackedAnchors als XRAnchorSet. Anker, die dort fehlen, verfolgt das System nicht mehr (etwa weil es sie verloren hat). Sie sollten dann auch aus der eigenen Verwaltung entfernt werden.
Rückgabewert
XRFrame.createAnchor() oder XRHitTestResult.createAnchor() bereitgestellt.Beispiele
AR-Session mit Anker-Feature starten und Anker erzeugen
const startAR = async () => {
if (!(await navigator.xr?.isSessionSupported('immersive-ar'))) {
console.log('immersive-ar wird nicht unterstützt');
return;
}
const session = await navigator.xr.requestSession('immersive-ar', {
requiredFeatures: ['anchors', 'local']
});
const refSpace = await session.requestReferenceSpace('local');
let anchorCreated = false;
const onFrame = (time, frame) => {
session.requestAnimationFrame(onFrame);
if (!anchorCreated) {
anchorCreated = true;
// Anker 1 m vor dem Ursprung des Referenzraums
const pose = new XRRigidTransform({ x: 0, y: 0, z: -1 });
frame.createAnchor(pose, refSpace)
.then((anchor) => console.log('Anker erstellt:', anchor))
.catch((err) => console.error('Anker fehlgeschlagen:', err));
}
};
session.requestAnimationFrame(onFrame);
};
document.querySelector('#ar-button').addEventListener('click', startAR);
Anker an einem Hit-Test-Treffer platzieren
const anchors = new Map(); // XRAnchor -> 3D-Objekt
// hitTestSource wurde vorher per session.requestHitTestSource() erzeugt
const placeOnSurface = async (frame, hitTestSource, createModel) => {
const [hit] = frame.getHitTestResults(hitTestSource);
if (!hit) return;
try {
const anchor = await hit.createAnchor();
anchors.set(anchor, createModel());
} catch (err) {
console.warn('Kein Anker möglich:', err.message);
}
};
Posen in jedem Frame aktualisieren und verlorene Anker aufräumen
const updateAnchors = (frame, refSpace) => {
for (const [anchor, model] of anchors) {
if (!frame.trackedAnchors.has(anchor)) {
// Das System verfolgt den Anker nicht mehr
model.visible = false;
anchors.delete(anchor);
continue;
}
const pose = frame.getPose(anchor.anchorSpace, refSpace);
if (pose) {
model.matrix.fromArray(pose.transform.matrix);
model.visible = true;
}
}
};
// Einzelnen Anker gezielt freigeben
const removeAnchor = (anchor) => {
anchor.delete();
anchors.delete(anchor);
};
// Wichtig · Fallstricke
- Kompatibilität: Die Schnittstelle ist experimentell. Unterstützt wird sie vor allem von Chrome/Edge auf Android mit ARCore und vom Meta Quest Browser. Firefox und Safari unterstützen sie nicht. Vor der Nutzung sollte man
'XRAnchor' in windowprüfen. - Nur im sicheren Kontext: WebXR funktioniert nur über HTTPS. Es kann eine Nutzergeste und eine Berechtigung erfordern. Außerdem muss
"anchors"inrequiredFeaturesoderoptionalFeaturesangefordert werden, sonst wird das Promise voncreateAnchor()abgelehnt. - Kein Konstruktor:
new XRAnchor()wirft einenTypeError. - Aufruf nur im aktiven Frame:
frame.createAnchor()darf nur innerhalb desrequestAnimationFrame-Callbacks der Session aufgerufen werden. Außerhalb davon wird einInvalidStateErrorausgelöst. - Pose kann fehlen:
getPose()kannnullzurückgeben, solange das Tracking unsicher ist. Den Rückgabewert daher immer prüfen. - Ressourcen: Anker kosten Rechenzeit beim Tracking. Nicht mehr benötigte Anker sollte man mit
delete()freigeben. Am Ende der Session werden alle Anker automatisch ungültig. requestPersistentHandle()ist nicht standardisiert und funktioniert nur in bestimmten Browsern.