Start · Sprachen · JavaScript · Referenz · XRInputSourcesChangeEvent

XRInputSourcesChangeEvent

Schnittstelle

Ereignisobjekt für <code>inputsourceschange</code> an einer <code>XRSession</code>: meldet, welche XR-Eingabequellen (Controller, Hände, Blick) hinzugekommen oder weggefallen sind.

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

Signatur

interface XRInputSourcesChangeEvent extends Event

Beschreibung

XRInputSourcesChangeEvent ist das Ereignisobjekt der WebXR Device API, das mit dem Ereignis inputsourceschange an eine XRSession geschickt wird. Das passiert immer dann, wenn sich die Menge der verfügbaren Eingabequellen ändert – etwa wenn ein Controller eingeschaltet, abgelegt oder durch Handtracking ersetzt wird, oder wenn der Nutzer einen Controller in die andere Hand nimmt.

Das Ereignis hat drei schreibgeschützte Eigenschaften:

  • session – die XRSession, in der sich die Eingabequellen geändert haben.
  • added – ein eingefrorenes Array mit den neu hinzugekommenen XRInputSource-Objekten.
  • removed – ein eingefrorenes Array mit den XRInputSource-Objekten, die nicht mehr verfügbar sind.

Mit dem Ereignis hält man eigene Datenstrukturen aktuell, zum Beispiel eine Map von Eingabequelle zu 3D-Controllermodell, statt in jedem Frame session.inputSources vollständig abzugleichen. Beim Start der Sitzung wird das Ereignis auch für schon vorhandene Eingabequellen ausgelöst. Deshalb eignet es sich gut als zentrale Stelle, an der Controllermodelle angelegt und wieder entfernt werden.

Normalerweise erzeugt der Browser das Ereignis selbst. Den Konstruktor new XRInputSourcesChangeEvent(type, init) braucht man fast nur für Tests oder zum Nachstellen von Ereignissen.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Name des Ereignisses, in der Praxis immer "inputsourceschange" (nur beim Konstruktor).
$eventInitDict Pflicht { session: XRSession, added: XRInputSource[], removed: XRInputSource[], bubbles?: boolean, cancelable?: boolean, composed?: boolean } Objekt zur Initialisierung. session, added und removed sind Pflicht, der Rest wird von EventInit übernommen.

Rückgabewert

Typ
XRInputSourcesChangeEvent
Beschreibung
Das Ereignisobjekt mit den schreibgeschützten Eigenschaften session, added und removed.

Beispiele

Hinzugekommene und entfernte Controller protokollieren (addEventListener)

const startXR = async () => {
  if (!navigator.xr || !(await navigator.xr.isSessionSupported('immersive-vr'))) {
    console.log('WebXR (immersive-vr) wird nicht unterstützt');
    return;
  }
  const session = await navigator.xr.requestSession('immersive-vr');

  const onInputSourcesChange = (event) => {
    for (const source of event.added) {
      console.log(`+ ${source.handedness} (${source.targetRayMode})`, source.profiles);
    }
    for (const source of event.removed) {
      console.log(`- ${source.handedness} (${source.targetRayMode})`);
    }
  };

  session.addEventListener('inputsourceschange', onInputSourcesChange);
  session.addEventListener('end', () => {
    session.removeEventListener('inputsourceschange', onInputSourcesChange);
  });
};

// requestSession braucht eine Nutzeraktion
document.querySelector('#enter-vr').addEventListener('click', startXR);
+ left (tracked-pointer) ['oculus-touch-v3', 'oculus-touch', 'generic-trigger-squeeze-thumbstick'] + right (tracked-pointer) ['oculus-touch-v3', 'oculus-touch', 'generic-trigger-squeeze-thumbstick']

Controllermodelle in einer Map verwalten (on-Property)

const controllerModels = new Map();

const createModel = (source) => ({
  name: `${source.handedness}-controller`,
  hasGamepad: Boolean(source.gamepad),
  dispose() { console.log(`${this.name} entfernt`); }
});

const setupInputTracking = (session) => {
  session.oninputsourceschange = ({ added, removed }) => {
    removed.forEach((source) => {
      controllerModels.get(source)?.dispose();
      controllerModels.delete(source);
    });
    added.forEach((source) => {
      controllerModels.set(source, createModel(source));
    });
    console.log('Aktive Modelle:', [...controllerModels.values()].map((m) => m.name));
  };
};

// Aufruf, z. B. nach requestSession():
// setupInputTracking(session);
Aktive Modelle: ['left-controller', 'right-controller'] left-controller entfernt Aktive Modelle: ['right-controller']

Ereignis zu Testzwecken selbst erzeugen

const simulateInputChange = (session, added = [], removed = []) => {
  const event = new XRInputSourcesChangeEvent('inputsourceschange', {
    session,
    added,
    removed
  });
  console.log(Object.isFrozen(event.added)); // true
  session.dispatchEvent(event);
};

// Beispiel: alle aktuellen Quellen als „hinzugefügt“ neu melden
// simulateInputChange(session, [...session.inputSources]);
true

// Wichtig · Fallstricke

  • Kompatibilität: Nur in Browsern mit WebXR-Unterstützung (Chrome/Edge auf Desktop und Android, Meta Quest Browser, Samsung Internet). Firefox und Safari auf dem Desktop unterstützen WebXR nicht. Visionen OS Safari unterstützt WebXR nur teilweise. Vorher navigator.xr und isSessionSupported() prüfen.
  • Sicherer Kontext: WebXR funktioniert nur über HTTPS bzw. auf localhost. requestSession() für immersive Sitzungen braucht außerdem eine Nutzeraktion, zum Beispiel einen Klick.
  • Handwechsel: Wechselt ein Controller die Hand (handedness), taucht dasselbe Gerät als neues XRInputSource-Objekt in added und das alte in removed auf. Deshalb immer beide Arrays auswerten.
  • Nicht selbst verändern: added und removed sind eingefrorene Arrays. Das Ereignis ist weder bubbelnd noch abbrechbar.
  • Keine Positionsdaten: Das Ereignis enthält keine Posen. Position und Ausrichtung holt man pro Frame über frame.getPose(source.gripSpace, refSpace).
  • Listener beim Ereignis end der Sitzung aufräumen, damit keine Verweise auf alte Eingabequellen zurückbleiben.