Start · Sprachen · JavaScript · Referenz · XRAnchor

XRAnchor

Schnittstelle

Ein <code>XRAnchor</code> steht für einen Punkt, der relativ zur realen Welt fixiert ist. Das System verfolgt seine Pose über die Zeit und korrigiert sie bei Bedarf.

seit JavaScript WebXR Anchors Module – experimentell (Chrome/Edge Kategorie: webapi

Signatur

interface XRAnchor

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): ein XRSpace, mit dem man in jedem Frame per frame.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 ein Promise<string> mit einer UUID zurück. Damit lässt sich der Anker in einer späteren Session über XRSession.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

Typ
XRAnchor
Beschreibung
Wird über das Promise von 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 erstellt: XRAnchor {anchorSpace: XRSpace}

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 window prüfen.
  • Nur im sicheren Kontext: WebXR funktioniert nur über HTTPS. Es kann eine Nutzergeste und eine Berechtigung erfordern. Außerdem muss "anchors" in requiredFeatures oder optionalFeatures angefordert werden, sonst wird das Promise von createAnchor() abgelehnt.
  • Kein Konstruktor: new XRAnchor() wirft einen TypeError.
  • Aufruf nur im aktiven Frame: frame.createAnchor() darf nur innerhalb des requestAnimationFrame-Callbacks der Session aufgerufen werden. Außerhalb davon wird ein InvalidStateError ausgelöst.
  • Pose kann fehlen: getPose() kann null zurü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.