Start · Sprachen · JavaScript · Referenz · XRSession: squeezestart

XRSession: squeezestart

Ereignis

Wird an eine <code>XRSession</code> gesendet, sobald der Benutzer an einer Eingabequelle eine primäre Greif- bzw. Quetschaktion (etwa am Grip-Taster) beginnt.

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

Signatur

xrSession.addEventListener("squeezestart", handler)

Beschreibung

Das Ereignis squeezestart gehört zur WebXR Device API. Es wird ausgelöst, wenn der Benutzer die primäre Quetschaktion (engl. primary squeeze action) einer Eingabequelle beginnt. Bei typischen VR-Controllern ist das der seitliche Grip-Taster, bei Hand-Tracking eine Greifgeste der Hand. Das Ereignisobjekt ist ein XRInputSourceEvent. Es enthält die auslösende Eingabequelle (inputSource) und ein XRFrame (frame), mit dem sich die Pose des Controllers genau zum Zeitpunkt der Aktion bestimmen lässt.

Meist nutzt man squeezestart für Greif- und Halte-Interaktionen, zum Beispiel um ein virtuelles Objekt aufzuheben, solange die Grip-Taste gedrückt ist. Zu jedem squeezestart gehört ein späteres squeezeend. Wird die Aktion vollständig abgeschlossen (Taste losgelassen, statt dass die Aktion abgebrochen wird), kommt zusätzlich ein squeeze-Ereignis. Die Reihenfolge ist also squeezestart → (squeeze) → squeezeend.

Einen Handler registriert man entweder mit addEventListener("squeezestart", handler) oder über die Eigenschaft XRSession.onsqueezestart. Das Ereignis lässt sich nicht abbrechen und steigt nicht im DOM auf, weil XRSession ein eigenständiges EventTarget ist.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Ereignisname "squeezestart".
$handler Pflicht (event: XRInputSourceEvent) => void Callback, der ein XRInputSourceEvent erhält. Wichtige Eigenschaften sind event.inputSource (die auslösende XRInputSource) und event.frame (ein XRFrame, der nur während des Handler-Aufrufs gültig ist).
$options boolean | AddEventListenerOptions false Die üblichen Optionen von addEventListener, etwa { once: true } oder { signal }.

Rückgabewert

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

Beispiele

Objekt greifen mit addEventListener

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

// Merkt sich, welche Eingabequelle gerade greift
const greifendeQuellen = new Set();

session.addEventListener("squeezestart", (event) => {
  const { inputSource, frame } = event;
  if (!inputSource.gripSpace) return; // z. B. reine Blick-Eingabe

  // Pose genau im Moment des Greifens ermitteln
  const pose = frame.getPose(inputSource.gripSpace, refSpace);
  if (pose) {
    const { x, y, z } = pose.transform.position;
    console.log(`Greifen begonnen (${inputSource.handedness}) bei`, x.toFixed(2), y.toFixed(2), z.toFixed(2));
    greifendeQuellen.add(inputSource);
  }
});

session.addEventListener("squeezeend", (event) => {
  greifendeQuellen.delete(event.inputSource);
  console.log("Greifen beendet:", event.inputSource.handedness);
});
Greifen begonnen (right) bei 0.21 1.12 -0.35 Greifen beendet: right

Handler über die on-Property setzen und entfernen

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

session.onsqueezestart = (event) => {
  console.log("squeezestart von", event.inputSource.handedness);
};

// Später deaktivieren, z. B. im Menümodus
const greifenDeaktivieren = () => {
  session.onsqueezestart = null;
};

session.addEventListener("end", greifenDeaktivieren);
squeezestart von left

Listener mit AbortController wieder entfernen

const session = await navigator.xr.requestSession("immersive-ar", {
  optionalFeatures: ["hand-tracking"]
});
const controller = new AbortController();

const onSqueezeStart = (event) => {
  const quelle = event.inputSource;
  const art = quelle.hand ? "Hand" : "Controller";
  console.log(`${art} beginnt Greifgeste`);
  // Haptisches Feedback, falls vorhanden
  quelle.gamepad?.hapticActuators?.[0]?.pulse?.(0.6, 50);
};

session.addEventListener("squeezestart", onSqueezeStart, { signal: controller.signal });

// Variante 1: gezielt entfernen
// session.removeEventListener("squeezestart", onSqueezeStart);
// Variante 2: alle über das Signal registrierten Listener entfernen
setTimeout(() => controller.abort(), 30_000);
Controller beginnt Greifgeste

// Wichtig · Fallstricke

  • event.frame ist nur während des Handlers gültig. Wenn Sie getPose() später aufrufen, etwa nach einem await oder in einem setTimeout, wird eine InvalidStateError-Ausnahme ausgelöst. Wenn Sie die Pose brauchen, ermitteln Sie sie deshalb synchron im Handler.
  • Nicht jede Eingabequelle kann „quetschen“. Blick-Eingaben (targetRayMode: "gaze") oder Bildschirmberührungen in AR ("screen") haben oft keine primäre Quetschaktion. Dann wird squeezestart nie ausgelöst. Für die Hauptauswahl verwenden Sie selectstart.
  • Bricht die Sitzung ab oder wird ein Controller getrennt, kann statt squeeze nur squeezeend ankommen. Setzen Sie den Greifzustand daher immer in squeezeend zurück, nicht in squeeze.
  • Sekundäre Tasten lösen kein squeezestart aus. Solche Tasten und analoge Druckwerte fragen Sie über inputSource.gamepad im Frame-Loop ab.
  • Kompatibilität: WebXR braucht einen sicheren Kontext (HTTPS). Unterstützt wird es in Chromium-basierten Browsern und im Meta Quest Browser. Firefox und Safari auf dem Desktop unterstützen WebXR nicht. Prüfen Sie die Verfügbarkeit mit navigator.xr?.isSessionSupported().