Start · Sprachen · JavaScript · Referenz · XRSession: selectend

XRSession: selectend

Ereignis

Wird an eine <code>XRSession</code> gesendet, wenn eine Eingabequelle ihre primäre Aktion beendet oder während einer laufenden primären Aktion getrennt wird.

seit JavaScript WebXR Device API – Chromium-basierte Browser (Chro Kategorie: webapi

Signatur

xrSession.addEventListener("selectend", handler)

Beschreibung

Das Ereignis selectend gehört zu den drei Auswahl-Ereignissen der WebXR Device API: selectstart, select und selectend. Es wird ausgelöst, sobald die primäre Aktion einer Eingabequelle endet. Das kann z. B. das Loslassen des Trigger-Knopfs am Controller sein, das Ende einer Pinch-Geste beim Hand-Tracking oder das Abheben des Fingers vom Bildschirm in einer AR-Sitzung auf dem Smartphone.

Wichtig: selectend wird immer ausgelöst, wenn vorher ein selectstart kam. Das gilt auch, wenn die Aktion abgebrochen wurde, etwa weil der Controller getrennt wurde oder die Sitzung endet. select dagegen wird nur bei einer erfolgreich abgeschlossenen Aktion ausgelöst, und zwar vor selectend. Deshalb ist selectend der richtige Ort für Aufräumarbeiten: gegriffene Objekte loslassen, Hervorhebungen entfernen oder Zustandsvariablen zurücksetzen.

Der Handler bekommt ein XRInputSourceEvent. Dessen Eigenschaft inputSource gibt an, welche Eingabequelle betroffen ist (z. B. linke oder rechte Hand). Über frame kommt man an ein XRFrame, mit dem sich die Pose der Eingabequelle zum Zeitpunkt des Ereignisses abfragen lässt. Registrieren kann man den Handler mit addEventListener("selectend", …) oder über die Eigenschaft onselectend.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Ereignisname "selectend".
$handler Pflicht (event: XRInputSourceEvent) => void Callback, der ein XRInputSourceEvent mit den Eigenschaften 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 Rückgabewert des Handlers wird nicht ausgewertet.

Beispiele

Gegriffenes Objekt beim Loslassen freigeben

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

// Pro Eingabequelle merken, welches Objekt gehalten wird
const held = new Map();

session.addEventListener('selectstart', (event) => {
  held.set(event.inputSource, { name: 'Würfel' });
  console.log(`Greifen gestartet (${event.inputSource.handedness})`);
});

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

  // Pose zum Zeitpunkt des Loslassens bestimmen
  const pose = event.frame.getPose(event.inputSource.targetRaySpace, 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));
  }
  held.delete(event.inputSource);
});
Greifen gestartet (right) Würfel losgelassen bei 0.21 1.34 -0.52

Abbruch von erfolgreicher Auswahl unterscheiden

const session = await navigator.xr.requestSession('immersive-ar');
let completed = false;

session.addEventListener('selectstart', () => { completed = false; });

// 'select' kommt nur bei erfolgreich abgeschlossener Aktion, vor 'selectend'
session.addEventListener('select', () => { completed = true; });

session.addEventListener('selectend', () => {
  console.log(completed ? 'Aktion abgeschlossen' : 'Aktion abgebrochen (z. B. Controller getrennt)');
});
Aktion abgeschlossen

on-Property verwenden und wieder entfernen

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

const onSelectEnd = (event) => {
  console.log('selectend von', event.inputSource.targetRayMode);
};

// Variante 1: on-Property
session.onselectend = onSelectEnd;

// Variante 2: addEventListener, später wieder entfernen
session.addEventListener('selectend', onSelectEnd);
session.removeEventListener('selectend', onSelectEnd);

// on-Property zurücksetzen
session.onselectend = null;
selectend von tracked-pointer

// Wichtig · Fallstricke

  • Immer aufräumen: selectend kommt auch bei Abbruch (Controller getrennt, Sitzung beendet). Erfolgsaktionen gehören deshalb in select, Aufräumarbeiten in selectend.
  • Das übergebene event.frame gilt nur während des Handlers. getPose() darf also nicht asynchron danach aufgerufen werden, sonst kommt es zu einem InvalidStateError.
  • Mehrere Eingabequellen, etwa zwei Controller, können gleichzeitig aktiv sein. Den Zustand deshalb pro inputSource verwalten, nicht in einer globalen Variable.
  • Für den sekundären Knopf (Grip/Squeeze) gibt es die eigenen Ereignisse squeezestart, squeeze und squeezeend.
  • Kompatibilität: WebXR funktioniert nur in sicheren Kontexten (HTTPS) und wird hauptsächlich von Chromium-Browsern und dem Meta Quest Browser unterstützt. Firefox und Safari (Desktop) unterstützen es nicht; Safari auf visionOS unterstützt WebXR. Vorher mit navigator.xr?.isSessionSupported() prüfen.