Signatur
Beschreibung
Die Methode createAnchor() gehört zum WebXR Anchors Module und erweitert die Schnittstelle XRHitTestResult. Sie erzeugt aus einem Treffer eines Hit-Tests, also dem Schnittpunkt eines Strahls mit einer erkannten realen Fläche wie Boden, Tisch oder Wand, einen Anker (XRAnchor). Das Gerät führt einen Anker fortlaufend nach. Er bleibt deshalb auch dann an derselben Stelle der realen Welt, wenn das System sein Bild der Umgebung nachträglich korrigiert, etwa weil eine Fläche genauer erkannt wurde.
Gegenüber XRFrame.createAnchor(pose, space) hat die Hit-Test-Variante einen Vorteil: Der Anker wird direkt an das getroffene reale Objekt gebunden. Wenn das System die Lage dieser Fläche anpasst, wandert der Anker mit. Typisch ist das in AR-Anwendungen, in denen Nutzer virtuelle Objekte wie Möbel, Markierungen oder Notizen auf echten Flächen ablegen und die Objekte dort stabil bleiben sollen.
Die Methode funktioniert nur in einer immersive-ar-Sitzung, bei der die Features "hit-test" und "anchors" angefordert wurden. Sie gibt ein Promise zurück. Der fertige Anker ist ab dem nächsten Frame in XRFrame.trackedAnchors enthalten. Seine aktuelle Lage fragt man in jedem Frame mit frame.getPose(anchor.anchorSpace, referenceSpace) ab.
Rückgabewert
Promise, das mit dem neu erzeugten XRAnchor erfüllt wird. Es wird abgelehnt, zum Beispiel mit NotSupportedError, wenn das Feature "anchors" nicht aktiviert ist, mit InvalidStateError, wenn die Sitzung beendet oder der Frame nicht mehr aktiv ist, oder mit OperationError, wenn das System den Anker nicht anlegen konnte.Beispiele
AR-Sitzung mit Hit-Test und Ankern starten
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: ['hit-test', 'anchors'],
optionalFeatures: ['dom-overlay'],
domOverlay: { root: document.body }
});
const refSpace = await session.requestReferenceSpace('local');
const viewerSpace = await session.requestReferenceSpace('viewer');
// Strahl aus der Bildschirmmitte in Blickrichtung
const hitTestSource = await session.requestHitTestSource({ space: viewerSpace });
return { session, refSpace, hitTestSource };
};
// Muss durch eine Nutzeraktion ausgelöst werden
document.querySelector('#ar-button').addEventListener('click', startAR);
Beim Tippen einen Anker am Hit-Test-Treffer anlegen
const anchors = new Set();
let latestHit = null;
const onXRFrame = (time, frame) => {
const session = frame.session;
session.requestAnimationFrame(onXRFrame);
const hits = frame.getHitTestResults(hitTestSource);
latestHit = hits.length > 0 ? hits[0] : null;
};
session.addEventListener('select', async () => {
if (!latestHit) return;
try {
const anchor = await latestHit.createAnchor();
anchors.add(anchor);
console.log('Anker erstellt, Anzahl:', anchors.size);
} catch (err) {
console.error('Anker konnte nicht erstellt werden:', err.name);
}
});
session.requestAnimationFrame(onXRFrame);
Verankerte Objekte in jedem Frame positionieren und wieder löschen
const drawAnchoredObjects = (frame, refSpace) => {
for (const anchor of anchors) {
// Wird der Anker nicht mehr verfolgt, fehlt er in trackedAnchors
if (!frame.trackedAnchors.has(anchor)) {
anchors.delete(anchor);
continue;
}
const pose = frame.getPose(anchor.anchorSpace, refSpace);
if (pose) {
// pose.transform.matrix ist eine Float32Array(16) für den Renderer
renderModelAt(pose.transform.matrix);
}
}
};
// Alle Anker entfernen, z. B. über einen "Zurücksetzen"-Button
const clearAnchors = () => {
for (const anchor of anchors) anchor.delete();
anchors.clear();
};
// Wichtig · Fallstricke
- Experimentelle API: Die Methode läuft derzeit praktisch nur in Chromium-Browsern auf Android mit ARCore, zum Beispiel Chrome ab Version 85. Firefox und Safari unterstützen sie nicht, auf Desktop-Rechnern gibt es in der Regel kein
immersive-ar. Vor der Nutzung sollte man die Unterstützung prüfen: mitisSessionSupported('immersive-ar')und mit'createAnchor' in XRHitTestResult.prototype. - Feature anfordern: Ohne
"anchors"inrequiredFeaturesoderoptionalFeatureswird das Promise abgelehnt. Ein Feature unteroptionalFeatureskann der Browser verweigern. Deshalb sollte man die Ablehnung immer mittry/catchabfangen. - Nur im aktiven Frame gültig: Ein
XRHitTestResultgilt nur für den Frame, in dem es entstanden ist. Einen Anker aus einem veralteten Ergebnis zu erzeugen, kann scheitern. Deshalb am besten zeitnah zum Frame aufrufen, etwa imselect-Ereignis mit dem Treffer aus dem letzten Frame. - Asynchron: Der Anker ist nicht sofort in
frame.trackedAnchorsenthalten. Außerdem kann das Tracking jederzeit abreißen. In diesem Fall fehlt der Anker intrackedAnchors, odergetPose()liefertnull. - Ressourcen: Anker kosten Rechenleistung beim Tracking. Nicht mehr benötigte Anker sollte man mit
XRAnchor.delete()freigeben. Beim Ende der Sitzung werden alle Anker automatisch ungültig. - Sicherheit und Datenschutz: Die API funktioniert nur in einem sicheren Kontext (HTTPS). Die Sitzung braucht eine Nutzeraktion und gegebenenfalls eine Berechtigung, weil Anker Rückschlüsse auf die reale Umgebung erlauben.