Start · Sprachen · JavaScript · Referenz · XRInputSourceEvent.frame

XRInputSourceEvent.frame

Eigenschaft

Schreibgeschützte Eigenschaft, die das <code>XRFrame</code> liefert, in dem das WebXR-Eingabeereignis (z. B. <code>select</code> oder <code>squeeze</code>) aufgetreten ist.

seit JavaScript WebXR Device API; Chrome/Edge 79+, Meta Quest Brow Kategorie: webapi

Signatur

XRInputSourceEvent.frame

Beschreibung

Die Eigenschaft frame eines XRInputSourceEvent enthält ein XRFrame-Objekt. Es gibt den Zustand der XR-Welt genau zu dem Zeitpunkt wieder, an dem die Benutzereingabe stattfand. So kannst du die Position und Ausrichtung des Controllers, der Hand oder des Blickstrahls zum Zeitpunkt der Aktion bestimmen und musst nicht auf den nächsten Animationsframe warten.

Normalerweise rufst du im Handler event.frame.getPose(event.inputSource.targetRaySpace, referenceSpace) auf. Damit erhältst du den Zielstrahl, mit dem du zielst, Objekte auswählst, schießt oder Hit-Tests auswertest. Für Greifgesten (squeeze) nimmst du meist gripSpace, damit ein Objekt an der Hand ausgerichtet wird.

Wichtig: Dieses Frame ist ein sogenanntes Ereignis-Frame und kein Animationsframe. Es ist nur während der synchronen Ausführung des Event-Handlers aktiv. Danach sind seine Methoden nicht mehr nutzbar. Außerdem darfst du auf einem Ereignis-Frame kein getViewerPose() aufrufen, denn das ist nur in Callbacks von requestAnimationFrame() erlaubt.

Rückgabewert

Typ
XRFrame
Beschreibung
Das XRFrame, in dem das Eingabeereignis ausgelöst wurde. Es ist nur innerhalb des Event-Handlers aktiv.

Beispiele

Zielstrahl beim select-Ereignis auslesen

const session = await navigator.xr.requestSession('immersive-vr');
const refSpace = await session.requestReferenceSpace('local');

session.addEventListener('select', (event) => {
  // Pose des Zielstrahls genau zum Zeitpunkt der Eingabe
  const pose = event.frame.getPose(event.inputSource.targetRaySpace, refSpace);
  if (!pose) return; // Tracking kann verloren sein

  const { position, orientation } = pose.transform;
  console.log('Strahl-Ursprung:', position.x.toFixed(2), position.y.toFixed(2), position.z.toFixed(2));
  console.log('Hand:', event.inputSource.handedness);
});
Strahl-Ursprung: 0.21 1.34 -0.18 Hand: right

Objekt beim Greifen (squeezestart) an die Hand heften

let grabbed = null;

session.addEventListener('squeezestart', (event) => {
  const { inputSource, frame } = event;
  if (!inputSource.gripSpace) return; // z. B. Blickeingabe ohne Grip

  const gripPose = frame.getPose(inputSource.gripSpace, refSpace);
  if (gripPose) {
    grabbed = { source: inputSource, matrix: gripPose.transform.matrix };
    console.log('Objekt gegriffen mit', inputSource.handedness);
  }
});

session.addEventListener('squeezeend', () => {
  grabbed = null;
  console.log('Objekt losgelassen');
});
Objekt gegriffen mit left Objekt losgelassen

Fallstrick: Frame außerhalb des Handlers verwenden

let savedFrame = null;

session.addEventListener('select', (event) => {
  savedFrame = event.frame; // Referenz speichern ...
  // Richtig: Pose sofort auslesen und die Daten speichern
  const pose = event.frame.getPose(event.inputSource.targetRaySpace, refSpace);
  console.log('Sofort ausgelesen:', pose !== null);

  setTimeout(() => {
    try {
      // ... aber hier ist das Frame nicht mehr aktiv
      savedFrame.getPose(event.inputSource.targetRaySpace, refSpace);
    } catch (err) {
      console.log(err.name);
    }
  }, 0);
});
Sofort ausgelesen: true InvalidStateError

// Wichtig · Fallstricke

  • Nur synchron gültig: Das Frame ist nur während der Ausführung des Handlers aktiv. Wenn du es später oder nach einem await verwendest, werfen Methoden wie getPose() einen InvalidStateError. Lies die benötigten Daten deshalb sofort aus und speichere sie, nicht das Frame selbst.
  • Kein getViewerPose(): Auf Ereignis-Frames wirft der Aufruf einen InvalidStateError. Die Pose des Betrachters bekommst du nur im Callback von XRSession.requestAnimationFrame().
  • getPose() kann null zurückgeben, wenn das Tracking gerade verloren ist. Prüfe den Wert deshalb immer.
  • Nicht jede Eingabequelle hat einen gripSpace, z. B. Blick- oder Bildschirmeingaben (targetRayMode 'gaze' bzw. 'screen').
  • Kompatibilität: WebXR funktioniert nur in sicheren Kontexten (HTTPS). Unterstützt wird es in Chromium-Browsern (Chrome, Edge, Samsung Internet), im Meta Quest Browser und in Safari auf visionOS, aber nicht in Firefox. Prüfe die Unterstützung vorher mit navigator.xr?.isSessionSupported().