Start · Sprachen · JavaScript · Referenz · XRInputSource

XRInputSource

Schnittstelle

Beschreibt eine einzelne Eingabequelle einer WebXR-Sitzung, z. B. einen Handcontroller, eine getrackte Hand, Blickrichtung oder einen Touchscreen-Tipp.

seit JavaScript WebXR Device API – Chromium 79+ (Chrome, Edge, Met Kategorie: webapi

Signatur

interface XRInputSource

Beschreibung

XRInputSource steht für genau ein Eingabegerät, mit dem der Benutzer in einer WebXR-Sitzung interagiert: einen Motion-Controller in der linken oder rechten Hand, eine per Kamera getrackte Hand, ein blickgesteuertes System (Gaze) oder einen Tipp auf den Bildschirm bei AR auf dem Smartphone. Man erzeugt diese Objekte nicht selbst. Der Browser stellt sie über XRSession.inputSources bereit, eine Liste vom Typ XRInputSourceArray, sowie über die Eigenschaft inputSource von Events wie select, squeeze und inputsourceschange.

Die wichtigsten Eigenschaften (alle schreibgeschützt):

  • handedness: "left", "right" oder "none".
  • targetRayMode: "tracked-pointer", "gaze", "screen" oder "transient-pointer". Beschreibt, wie der Zielstrahl entsteht.
  • targetRaySpace: ein XRSpace für den Zielstrahl, etwa zum Zeigen und Auswählen per Raycast.
  • gripSpace: ein XRSpace für die Handposition, um ein Controller-Modell darzustellen. Ist null, wenn das Gerät nicht gehalten wird, z. B. bei Gaze.
  • gamepad: ein Gamepad-Objekt mit Tasten und Achsen (Layout "xr-standard") oder null.
  • hand: ein XRHand mit 25 Gelenken, wenn Hand-Tracking aktiv ist, sonst null.
  • profiles: ein Array von Profil-Kennungen wie ["oculus-touch-v3", "generic-trigger-squeeze-thumbstick"], sortiert vom spezifischsten zum allgemeinsten Profil.

Typischer Ablauf: In jedem Frame (XRSession.requestAnimationFrame) geht man die Liste session.inputSources durch, fragt mit frame.getPose(source.targetRaySpace, refSpace) die Lage des Zielstrahls ab und zeichnet Laserstrahl und Controller-Modell. Aktionen wie „Auswählen“ oder „Greifen“ verarbeitet man am besten über die Events select und squeeze. Für eigene Tastenbelegungen fragt man gamepad.buttons und gamepad.axes ab.

Rückgabewert

Typ
XRInputSource
Beschreibung
Wird nicht per Konstruktor erzeugt. Instanzen kommen aus XRSession.inputSources oder aus event.inputSource von XRInputSourceEvent.

Beispiele

Eingabequellen einer Sitzung auflisten

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.join(', ')}`
    );
  }
  for (const source of event.removed) {
    console.log(`Entfernt: ${source.handedness}`);
  }
});
Neu: left | tracked-pointer | oculus-touch-v3, generic-trigger-squeeze-thumbstick Neu: right | tracked-pointer | oculus-touch-v3, generic-trigger-squeeze-thumbstick

Zielstrahl und Griff-Pose in jedem Frame auslesen

const refSpace = await session.requestReferenceSpace('local-floor');

const onFrame = (time, frame) => {
  session.requestAnimationFrame(onFrame);

  for (const source of session.inputSources) {
    const rayPose = frame.getPose(source.targetRaySpace, refSpace);
    if (rayPose) {
      const { position } = rayPose.transform;
      // Laserstrahl ab Controller-Position zeichnen
      console.log(source.handedness, position.x.toFixed(2), position.y.toFixed(2), position.z.toFixed(2));
    }

    if (source.gripSpace) {
      const gripPose = frame.getPose(source.gripSpace, refSpace);
      // gripPose?.transform.matrix für das Controller-3D-Modell verwenden
    }
  }
};

session.requestAnimationFrame(onFrame);
right 0.21 1.12 -0.35

Auswahl und Greifen über Events verarbeiten

session.addEventListener('select', (event) => {
  const { inputSource, frame } = event;
  const pose = frame.getPose(inputSource.targetRaySpace, refSpace);
  if (pose) {
    console.log(`Auswahl mit ${inputSource.handedness}er Hand`);
    // Raycast in die Szene entlang pose.transform
  }
});

session.addEventListener('squeeze', ({ inputSource }) => {
  console.log(`Greifen: ${inputSource.handedness}`);
});
Auswahl mit rightr Hand

Thumbstick über das Gamepad-Objekt abfragen

const readThumbstick = (source) => {
  const gp = source.gamepad;
  if (!gp || gp.mapping !== 'xr-standard') return null;
  // xr-standard: axes[2]/axes[3] = Thumbstick X/Y, buttons[0] = Trigger
  return {
    x: gp.axes[2] ?? 0,
    y: gp.axes[3] ?? 0,
    trigger: gp.buttons[0]?.value ?? 0,
  };
};

for (const source of session.inputSources) {
  const state = readThumbstick(source);
  if (state) console.log(source.handedness, state);
}
left { x: 0, y: -0.87, trigger: 0 }

// Wichtig · Fallstricke

  • Kompatibilität: Wird von Chromium-Browsern (Chrome, Edge, Meta Quest Browser, Samsung Internet) und Safari auf der Apple Vision Pro unterstützt, dort vor allem mit "transient-pointer". Firefox auf dem Desktop unterstützt WebXR nicht. Die API funktioniert nur in sicheren Kontexten (HTTPS) und kann per Permissions-Policy xr-spatial-tracking gesperrt sein.
  • Instanzen können sich ändern: Wenn ein Controller neu verbunden wird oder zwischen Controller und Hand-Tracking umgeschaltet wird, entstehen neue Objekte. Man sollte daher keine Referenzen dauerhaft zwischenspeichern, sondern auf inputsourceschange reagieren.
  • Posen können fehlen: frame.getPose() gibt null zurück, wenn das Tracking verloren geht. gripSpace, gamepad und hand können ebenfalls null sein. Diese Fälle immer abfragen.
  • transient-pointer und screen existieren nur während einer Interaktion und tauchen dann kurz in inputSources auf.
  • Hand-Tracking muss beim Start mit optionalFeatures: ['hand-tracking'] angefordert werden, sonst ist hand immer null.
  • Datenschutz: Wenn die Seite nicht im Fokus ist (visibilityState ist "visible-blurred"), liefert der Browser keine Eingabedaten. profiles kann aus Datenschutzgründen generisch gehalten sein.
  • Controller-Modelle passend zu profiles liefert die Bibliothek @webxr-input-profiles/motion-controllers.