Start · Sprachen · JavaScript · Referenz · XRSession: squeezeend

XRSession: squeezeend

Ereignis

Wird an eine <code>XRSession</code> gesendet, wenn eine Eingabequelle ihre primäre Greifaktion (Squeeze) beendet, abbricht oder während der Aktion getrennt wird.

seit JavaScript WebXR Device API – Chromium-Browser (Chrome/Edge 7 Kategorie: webapi

Signatur

xrSession.addEventListener("squeezeend", handler)

Beschreibung

Das Ereignis squeezeend gehört zur WebXR Device API. Es wird an eine XRSession gesendet, wenn eine Eingabequelle ihre primäre Greifaktion (engl. primary squeeze action) beendet. Typisch ist das Loslassen der Grip-Taste an einem VR-Controller oder das Öffnen der Faust beim Hand-Tracking. Die MDN-Kurzbeschreibung spricht von der „primären Aktion“. Gemeint ist aber die Greifaktion. Für die primäre Aktion (z. B. den Trigger) gibt es das eigene Ereignis selectend.

Das Ereignis wird immer ausgelöst, wenn eine Greifaktion endet, egal wie. Das gilt, wenn die Aktion normal abgeschlossen wurde (dann kommt vorher ein squeeze-Ereignis), wenn sie abgebrochen wurde, oder wenn der Controller während der Aktion getrennt wurde. Damit eignet sich squeezeend gut zum Aufräumen: Ein gegriffenes Objekt wird losgelassen, eine Hervorhebung wird entfernt, ein Zustand wird zurückgesetzt.

Die Reihenfolge ist: squeezestart → (optional) squeeze → squeezeend. Das Ereignisobjekt ist ein XRInputSourceEvent. Seine Eigenschaft inputSource nennt den betroffenen Controller bzw. die Hand, frame liefert einen XRFrame, mit dem man die Pose zum Zeitpunkt des Ereignisses abfragen kann.

Den Handler registriert man mit addEventListener("squeezeend", …) oder über die Eigenschaft onsqueezeend der Sitzung.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Ereignisname "squeezeend".
$handler Pflicht (event: XRInputSourceEvent) => void Callback, der ein XRInputSourceEvent mit inputSource (XRInputSource) und frame (XRFrame) erhält.
$options boolean | AddEventListenerOptions false Übliche Listener-Optionen wie once oder signal.

Rückgabewert

Typ
void
Beschreibung
addEventListener gibt nichts zurück. Der Handler erhält ein XRInputSourceEvent.

Beispiele

Gegriffenes Objekt beim Loslassen freigeben

const session = await navigator.xr.requestSession('immersive-vr');
const refSpace = await session.requestReferenceSpace('local');
const heldObjects = new Map(); // XRInputSource -> Objekt

session.addEventListener('squeezestart', (event) => {
  // Stellvertretend: Objekt in der Nähe des Controllers merken
  heldObjects.set(event.inputSource, { name: 'Würfel' });
});

session.addEventListener('squeezeend', (event) => {
  const obj = heldObjects.get(event.inputSource);
  if (!obj) return;

  // Pose zum Zeitpunkt des Loslassens bestimmen
  const pose = event.frame.getPose(event.inputSource.gripSpace, refSpace);
  if (pose) {
    const { x, y, z } = pose.transform.position;
    console.log(`${obj.name} losgelassen bei`, x.toFixed(2), y.toFixed(2), z.toFixed(2));
  }
  heldObjects.delete(event.inputSource);
});
Würfel losgelassen bei 0.12 1.05 -0.40

Abgebrochene von abgeschlossenen Greifaktionen unterscheiden

const session = await navigator.xr.requestSession('immersive-vr');
const completed = new WeakSet();

session.addEventListener('squeeze', (event) => {
  completed.add(event.inputSource); // Aktion erfolgreich abgeschlossen
});

session.onsqueezeend = (event) => {
  const hand = event.inputSource.handedness; // 'left' | 'right' | 'none'
  if (completed.has(event.inputSource)) {
    console.log(`Greifen (${hand}) abgeschlossen`);
    completed.delete(event.inputSource);
  } else {
    console.log(`Greifen (${hand}) abgebrochen oder Controller getrennt`);
  }
};
Greifen (right) abgeschlossen

Listener beim Sitzungsende entfernen

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

const onSqueezeEnd = (event) => {
  console.log('squeezeend von', event.inputSource.handedness);
};

session.addEventListener('squeezeend', onSqueezeEnd);

session.addEventListener('end', () => {
  session.removeEventListener('squeezeend', onSqueezeEnd);
  // Alternativ bei on-Property: session.onsqueezeend = null;
  console.log('Sitzung beendet, Listener entfernt');
}, { once: true });
squeezeend von left Sitzung beendet, Listener entfernt

// Wichtig · Fallstricke

  • Greifaktion, nicht primäre Aktion: squeezeend gehört zur Grip-Taste bzw. Greifgeste. Für Trigger oder Tippen sind selectstart, select und selectend zuständig.
  • Nicht jede Eingabequelle kann greifen: Blickgesteuerte Eingaben, Bildschirm-Taps oder einfache Controller haben oft keine Greifaktion. Dann wird squeezeend nie ausgelöst.
  • Immer aufräumen: Setze den Zustand in squeezeend zurück, nicht in squeeze. Sonst bleiben Objekte nach einem Abbruch oder einer Trennung „kleben“.
  • Das frame gilt nur kurz: event.frame ist nur innerhalb des Handlers aktiv. Speichere es nicht, um es später zu verwenden, denn dann wirft getPose() einen Fehler. getPose() kann außerdem null liefern, wenn das Tracking verloren ging.
  • Kompatibilität: WebXR braucht einen sicheren Kontext (HTTPS). Unterstützt wird es in Chromium-Browsern und im Meta Quest Browser, nicht in Firefox und Safari (Desktop). Prüfe die Unterstützung mit navigator.xr?.isSessionSupported().