Start · Sprachen · JavaScript · Referenz · XRInputSourcesChangeEvent.added

XRInputSourcesChangeEvent.added

Eigenschaft

Schreibgeschütztes Array mit den <code>XRInputSource</code>-Objekten, die seit dem letzten <code>inputsourceschange</code>-Ereignis neu verfügbar geworden sind.

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

Signatur

XRInputSourcesChangeEvent.added

Beschreibung

Die schreibgeschützte Eigenschaft added des XRInputSourcesChangeEvent ist ein eingefrorenes Array mit null oder mehr XRInputSource-Objekten. Jedes davon steht für eine Eingabequelle, die gerade neu verfügbar geworden ist, zum Beispiel ein Controller, der eingeschaltet oder verbunden wurde, eine Hand, die das Hand-Tracking erkannt hat, oder ein Blick- bzw. Bildschirm-Eingabegerät.

Das Ereignis wird als inputsourceschange an der XRSession ausgelöst. Registrieren kannst du es mit session.addEventListener("inputsourceschange", handler) oder über die Eigenschaft session.oninputsourceschange. Normalerweise wertest du added und removed zusammen aus, damit deine eigene Liste der Eingabequellen, die zugehörigen 3D-Modelle (etwa Controller-Meshes) und Zuordnungen wie „linke Hand/rechte Hand“ zur aktuellen Hardware passen.

Die meisten Informationen zu jeder neuen Quelle stehen sofort bereit: handedness, targetRayMode, profiles, gripSpace sowie gegebenenfalls gamepad und hand. Die aktuelle Position erhältst du aber erst im Render-Loop über XRFrame.getPose().

Rückgabewert

Typ
ReadonlyArray<XRInputSource>
Beschreibung
Ein eingefrorenes Array mit den neu hinzugekommenen XRInputSource-Objekten. Gibt es keine neuen Quellen, ist es leer.

Beispiele

Neue Controller protokollieren (addEventListener)

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

session.addEventListener("inputsourceschange", (event) => {
  for (const source of event.added) {
    console.log(
      `Neu: ${source.handedness} / ${source.targetRayMode}`,
      source.profiles
    );
  }
});
Neu: right / tracked-pointer ["oculus-touch-v3", "oculus-touch", "generic-trigger-squeeze-thumbstick"]

Eigene Map für Controller-Modelle aktuell halten

const controllerModels = new Map();

const createModelFor = (source) => ({ name: `Modell-${source.handedness}` });

const onInputSourcesChange = ({ added, removed }) => {
  for (const source of removed) {
    controllerModels.delete(source);
  }
  for (const source of added) {
    // Hand-Tracking und Controller getrennt behandeln
    if (source.hand) {
      console.log(`Hand erkannt: ${source.handedness}`);
      continue;
    }
    controllerModels.set(source, createModelFor(source));
  }
  console.log(`Aktive Controller: ${controllerModels.size}`);
};

const session = await navigator.xr.requestSession("immersive-vr", {
  optionalFeatures: ["hand-tracking"]
});
session.oninputsourceschange = onInputSourcesChange;
Aktive Controller: 2

Gamepad-Tasten neuer Quellen im Render-Loop auswerten

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

session.addEventListener("inputsourceschange", (e) => {
  e.added.filter((s) => s.gamepad).forEach((s) => gamepadSources.add(s));
  e.removed.forEach((s) => gamepadSources.delete(s));
});

const onFrame = (time, frame) => {
  for (const source of gamepadSources) {
    const pose = frame.getPose(source.gripSpace ?? source.targetRaySpace, refSpace);
    if (pose && source.gamepad.buttons[0]?.pressed) {
      console.log("Trigger gedrückt bei", pose.transform.position);
    }
  }
  session.requestAnimationFrame(onFrame);
};
session.requestAnimationFrame(onFrame);
Trigger gedrückt bei DOMPointReadOnly {x: 0.21, y: 1.05, z: -0.34, w: 1}

// Wichtig · Fallstricke

  • Eingefrorenes Array: added lässt sich nicht verändern. Mit push() o. ä. wirft der Code im Strict Mode einen Fehler. Kopiere den Inhalt deshalb in eine eigene Datenstruktur.
  • Anfangszustand: Quellen, die beim Start der Sitzung schon verbunden sind, meldet der Browser in der Regel über ein erstes inputsourceschange-Ereignis. Zur Sicherheit solltest du zusätzlich session.inputSources auswerten, falls dein Listener spät registriert wird.
  • Ersetzen statt Ändern: Ändern sich Eigenschaften einer Quelle (z. B. handedness oder profiles), entfernt der Browser das alte Objekt und legt ein neues an. Dasselbe Ereignis kann die Quelle dann in removed und ihren Nachfolger in added enthalten. Werte daher zuerst removed aus und danach added.
  • Referenzen: Verwende die XRInputSource-Objekte direkt als Schlüssel (z. B. in einer Map) und gib sie frei, sobald sie in removed auftauchen. Sonst entstehen Speicherlecks.
  • 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. Prüfe die Unterstützung vorher mit 'xr' in navigator.