Signatur
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
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);
});
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);
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);
// Wichtig · Fallstricke
event.frameist nur während des Handlers gültig. Wenn SiegetPose()später aufrufen, etwa nach einemawaitoder in einemsetTimeout, wird eineInvalidStateError-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 wirdsqueezestartnie ausgelöst. Für die Hauptauswahl verwenden Sieselectstart. - Bricht die Sitzung ab oder wird ein Controller getrennt, kann statt
squeezenursqueezeendankommen. Setzen Sie den Greifzustand daher immer insqueezeendzurück, nicht insqueeze. - Sekundäre Tasten lösen kein
squeezestartaus. Solche Tasten und analoge Druckwerte fragen Sie überinputSource.gamepadim 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().