Start · Sprachen · JavaScript · Referenz · Gamepad.pose

Gamepad.pose

Eigenschaft

Schreibgeschützte Eigenschaft, die ein <code>GamepadPose</code>-Objekt mit Position, Ausrichtung, Geschwindigkeit und Beschleunigung eines WebVR-Controllers liefert.

seit JavaScript WebVR 1.1 (experimentell, veraltet) – nur Firefox Kategorie: webapi

Signatur

Gamepad.pose

Beschreibung

Die Eigenschaft Gamepad.pose gehört zu den Erweiterungen, die die WebVR-API dem Gamepad-Interface hinzufügt. Sie gibt ein GamepadPose-Objekt zurück, das den aktuellen räumlichen Zustand eines VR-Controllers beschreibt, zum Beispiel eines Oculus-Touch- oder HTC-Vive-Controllers. Bei klassischen Gamepads ohne Positionsverfolgung ist der Wert null.

Das GamepadPose-Objekt stellt unter anderem diese Werte bereit:

  • hasPosition / hasOrientation: Wahrheitswerte, die angeben, ob das Gerät Position bzw. Ausrichtung überhaupt melden kann.
  • position: Float32Array mit [x, y, z] in Metern oder null.
  • orientation: Quaternion [x, y, z, w] als Float32Array oder null.
  • linearVelocity, linearAcceleration, angularVelocity, angularAcceleration: Bewegungsdaten, jeweils Float32Array oder null.

Die Pose wird wie alle Gamepad-Daten als Momentaufnahme geliefert. Du musst deshalb in jedem Frame (typischerweise in requestAnimationFrame bzw. VRDisplay.requestAnimationFrame) über navigator.getGamepads() neu abfragen, um aktuelle Werte zu bekommen.

Die WebVR-API ist veraltet und wurde durch die WebXR Device API ersetzt. Für neue Projekte solltest du Controller-Posen über XRInputSource.gripSpace bzw. targetRaySpace und XRFrame.getPose() ermitteln.

Rückgabewert

Typ
GamepadPose | null
Beschreibung
Ein GamepadPose-Objekt mit den aktuellen Pose-Daten des Controllers oder null, wenn das Gerät keine Pose-Informationen liefert.

Beispiele

Pose eines VR-Controllers pro Frame auslesen

const formatVec = (arr) => arr ? Array.from(arr, (v) => v.toFixed(2)).join(', ') : 'n/a';

const update = () => {
  for (const pad of navigator.getGamepads()) {
    // Nur Controller mit Pose-Unterstützung berücksichtigen
    if (!pad || !('pose' in pad) || !pad.pose) continue;

    const { pose } = pad;
    if (pose.hasPosition) {
      console.log(`${pad.id} Position: ${formatVec(pose.position)}`);
    }
    if (pose.hasOrientation) {
      console.log(`${pad.id} Ausrichtung: ${formatVec(pose.orientation)}`);
    }
  }
  requestAnimationFrame(update);
};

window.addEventListener('gamepadconnected', () => requestAnimationFrame(update), { once: true });
OpenVR Gamepad Position: 0.21, 1.05, -0.34 OpenVR Gamepad Ausrichtung: 0.01, 0.38, -0.02, 0.92

Feature-Erkennung: Gamepad mit oder ohne Pose

window.addEventListener('gamepadconnected', (event) => {
  const pad = event.gamepad;
  const supportsPose = 'pose' in pad && pad.pose !== null;
  console.log(`${pad.id}: ${supportsPose ? 'VR-Controller mit Pose' : 'klassisches Gamepad'}`);

  if (supportsPose) {
    console.log('Hand:', pad.hand || 'unbekannt');
  }
});
Xbox Wireless Controller: klassisches Gamepad

Moderne Alternative: Controller-Pose mit WebXR

const startXR = async () => {
  if (!navigator.xr || !(await navigator.xr.isSessionSupported('immersive-vr'))) {
    console.log('WebXR VR wird nicht unterstützt');
    return;
  }
  const session = await navigator.xr.requestSession('immersive-vr');
  const canvas = document.createElement('canvas');
  const gl = canvas.getContext('webgl', { xrCompatible: true });
  await session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) });
  const refSpace = await session.requestReferenceSpace('local');

  const onFrame = (time, frame) => {
    for (const source of session.inputSources) {
      if (!source.gripSpace) continue;
      const pose = frame.getPose(source.gripSpace, refSpace);
      if (pose) {
        const { x, y, z } = pose.transform.position;
        console.log(`${source.handedness}: ${x.toFixed(2)}, ${y.toFixed(2)}, ${z.toFixed(2)}`);
      }
    }
    session.requestAnimationFrame(onFrame);
  };
  session.requestAnimationFrame(onFrame);
};

// Muss durch eine Nutzeraktion ausgelöst werden
document.querySelector('#vr-button').addEventListener('click', startXR);
right: 0.24, 1.10, -0.30

// Wichtig · Fallstricke

  • Veraltet und experimentell: Gamepad.pose gehört zur eingestellten WebVR-API. Chrome hat sie nie standardmäßig ausgeliefert, Firefox hat WebVR entfernt bzw. nur noch hinter Flags. Verwende für neue Projekte die WebXR Device API.
  • Prüfe immer mit 'pose' in gamepad und auf null, bevor du darauf zugreifst. Einzelne Felder wie position können trotz vorhandenem Objekt null sein, deshalb zusätzlich hasPosition/hasOrientation auswerten.
  • Die Werte sind Momentaufnahmen: Ein einmal gespeichertes Gamepad-Objekt wird in Chromium-basierten Browsern nicht aktualisiert, frag deshalb in jedem Frame neu über navigator.getGamepads() ab.
  • Positionen sind in Metern relativ zum Tracking-Ursprung angegeben, die Ausrichtung als Quaternion [x, y, z, w], nicht als Euler-Winkel.
  • Die Gamepad-API gibt es nur in sicheren Kontexten (HTTPS). Außerdem kann sie per Permissions-Policy gamepad gesperrt sein.