Start · Sprachen · JavaScript · Referenz · XRFrame.createAnchor()

XRFrame.createAnchor()

Methode

Erzeugt asynchron einen frei platzierten <code>XRAnchor</code>, der eine Pose relativ zur realen Welt festhält, auch wenn das System sein Weltverständnis aktualisiert.

seit JavaScript WebXR Anchors Module; Chrome/Edge 85+ (Android, AR Kategorie: webapi

Signatur

XRFrame.prototype.createAnchor(pose, space)

Beschreibung

Mit createAnchor() legt man in einer immersiven AR-Sitzung einen Anker an. Das ist ein Punkt in der realen Welt, den das XR-System weiter verfolgt. Beim Tracking passt das Gerät sein Modell der Umgebung ständig an. Koordinaten, die man einfach selbst speichert, „driften“ deshalb mit der Zeit. Ein Anker korrigiert diese Abweichungen: Seine Position bleibt an der physischen Stelle, an der man ihn angelegt hat.

Die Methode nimmt eine XRRigidTransform (Position und Ausrichtung) und einen XRSpace als Bezugssystem. Das Ergebnis ist ein Promise, das mit einem XRAnchor erfüllt wird. Dessen anchorSpace fragt man danach in jedem Frame mit frame.getPose(anchor.anchorSpace, refSpace) ab und platziert darüber virtuelle Objekte.

Typische Einsätze sind z. B. ein virtuelles Möbelstück, das auf dem Boden liegen bleibt, oder Markierungen, die sich der Nutzer merkt. Soll der Anker an einer erkannten Fläche aus einem Hit-Test hängen, nimmt man besser XRHitTestResult.createAnchor(). Damit wird der Anker an die erkannte Fläche gebunden.

Für die Methode muss die Sitzung mit dem Feature "anchors" angefragt worden sein. Außerdem darf man sie nur auf einem aktiven Frame aufrufen, also innerhalb des requestAnimationFrame-Callbacks.

Parameter

Name Typ Default Beschreibung
$pose Pflicht XRRigidTransform Position und Ausrichtung des gewünschten Ankers, bezogen auf space.
$space Pflicht XRSpace Bezugssystem, in dem pose angegeben ist, z. B. ein XRReferenceSpace ("local") oder der targetRaySpace eines Controllers.

Rückgabewert

Typ
Promise<XRAnchor>
Beschreibung
Wird mit dem neu erzeugten XRAnchor erfüllt. Wird mit einem InvalidStateError (DOMException) abgelehnt, wenn der Frame nicht aktiv ist, oder mit NotSupportedError, wenn das Feature "anchors" nicht aktiviert ist bzw. das Gerät keine Anker anlegen kann.

Beispiele

AR-Sitzung mit Anker-Feature starten und Anker vor der Kamera anlegen

const startAR = async () => {
  const session = await navigator.xr.requestSession('immersive-ar', {
    requiredFeatures: ['anchors', 'local']
  });
  const refSpace = await session.requestReferenceSpace('local');
  const anchors = new Set();
  let pendingAnchor = true;

  const onFrame = (time, frame) => {
    session.requestAnimationFrame(onFrame);

    if (pendingAnchor) {
      pendingAnchor = false;
      // 1 Meter vor dem Ursprung des lokalen Raums
      const pose = new XRRigidTransform({ x: 0, y: 0, z: -1 });
      frame.createAnchor(pose, refSpace)
        .then((anchor) => {
          anchors.add(anchor);
          console.log('Anker erstellt');
        })
        .catch((err) => console.error('Anker fehlgeschlagen:', err.name));
    }

    // Alle Anker in jedem Frame abfragen
    for (const anchor of anchors) {
      const anchorPose = frame.getPose(anchor.anchorSpace, refSpace);
      if (anchorPose) {
        // Hier ein 3D-Objekt mit anchorPose.transform.matrix platzieren
      }
    }
  };

  session.requestAnimationFrame(onFrame);
};
Anker erstellt

Anker per Controller-Auswahl (select-Event) setzen

// Voraussetzung: session und refSpace wie oben
const anchors = new Set();

session.addEventListener('select', (event) => {
  const { frame, inputSource } = event;
  // Anker an der aktuellen Pose des Zielstrahls anlegen
  const identity = new XRRigidTransform();
  frame.createAnchor(identity, inputSource.targetRaySpace)
    .then((anchor) => {
      anchors.add(anchor);
      console.log(`Anker Nr. ${anchors.size} gesetzt`);
    })
    .catch((err) => console.warn(err.message));
});
Anker Nr. 1 gesetzt

Verlorene Anker erkennen und Anker löschen

const onFrame = (time, frame) => {
  session.requestAnimationFrame(onFrame);

  // trackedAnchors enthält alle Anker, die das System gerade verfolgt
  for (const anchor of anchors) {
    if (!frame.trackedAnchors.has(anchor)) {
      console.log('Anker nicht mehr verfolgt – wird entfernt');
      anchor.delete(); // Ressourcen beim System freigeben
      anchors.delete(anchor);
    }
  }
};
session.requestAnimationFrame(onFrame);
Anker nicht mehr verfolgt – wird entfernt

// Wichtig · Fallstricke

  • Feature anfordern: Ohne "anchors" in requiredFeatures oder optionalFeatures wird das Promise abgelehnt. Wurde das Feature nur optional angefragt, sollte man vor dem Aufruf mit typeof frame.createAnchor === 'function' prüfen, ob es die Methode gibt.
  • Nur aktive Frames: Man muss die Methode synchron im requestAnimationFrame-Callback oder in einem Eingabe-Event wie select aufrufen. Ein gespeicherter Frame, den man später benutzt, führt zu einem InvalidStateError.
  • Asynchron: Der Anker steht erst in einem späteren Frame zur Verfügung. getPose() kann anfangs null liefern, deshalb vor der Nutzung immer prüfen.
  • Ressourcen: Anker kosten das System Rechenzeit und Speicher. Nicht mehr benötigte Anker gibt man mit XRAnchor.delete() frei. Wie viele Anker möglich sind, hängt vom Gerät ab.
  • Kompatibilität: Die Methode ist experimentell. Unterstützt wird sie in Chromium-Browsern auf Android mit ARCore sowie teilweise auf Meta Quest (Meta Quest Browser). Firefox und Safari unterstützen sie nicht. WebXR setzt außerdem einen sicheren Kontext (HTTPS) voraus.
  • Datenschutz: Anker verraten Informationen über die Umgebung. Browser können deshalb eine Zustimmung des Nutzers verlangen.