Start · Sprachen · JavaScript · Referenz · GamepadPose

GamepadPose

Schnittstelle

Beschreibt die Pose eines WebVR-Controllers zu einem Zeitpunkt: Orientierung, Position, Geschwindigkeit und Beschleunigung als <code>Float32Array</code>-Werte.

seit JavaScript Experimentell, nicht standardisiert (WebVR-Erweite Kategorie: webapi

Signatur

interface GamepadPose

Beschreibung

Das Interface GamepadPose gehört zu den Erweiterungen der Gamepad API und liefert die räumliche Lage eines bewegungserfassten Controllers, etwa eines VR-Handcontrollers. Man bekommt es nicht über einen Konstruktor, sondern liest es über die Eigenschaft Gamepad.pose eines Gamepad-Objekts aus navigator.getGamepads() aus.

Eine Pose enthält alle Werte als schreibgeschützte Eigenschaften:

  • hasOrientation / hasPosition: boolean. Gibt an, ob der Controller Orientierung bzw. Position überhaupt melden kann.
  • position: Float32Array [x, y, z] in Metern, relativ zum Ursprung des Tracking-Raums.
  • linearVelocity / linearAcceleration: [x, y, z] in m/s bzw. m/s².
  • orientation: Quaternion [x, y, z, w].
  • angularVelocity / angularAcceleration: [x, y, z] in rad/s bzw. rad/s².

Jede Vektor-Eigenschaft kann null sein, wenn die Hardware den Wert nicht liefert. Die Werte bilden immer nur einen Moment ab. Wer eine aktuelle Pose braucht, muss das Gamepad in jedem Frame (z. B. in requestAnimationFrame) neu abfragen.

Das Interface stammt aus der Zeit von WebVR, das inzwischen eingestellt ist. Für neue Projekte ist die WebXR Device API gedacht. Dort liefern XRInputSource und XRFrame.getPose() die gleichen Informationen.

Rückgabewert

Typ
GamepadPose | null
Beschreibung
Wird über Gamepad.pose gelesen. Liefert ein GamepadPose-Objekt oder null, wenn das Gamepad keine Pose-Daten hat.

Beispiele

Pose eines Controllers in jedem Frame auslesen

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

const loop = () => {
  for (const pad of navigator.getGamepads()) {
    if (!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} Orientierung: ${formatVec(pose.orientation)}`);
    }
  }
  requestAnimationFrame(loop);
};

requestAnimationFrame(loop);
OpenVR Gamepad Position: 0.12, 1.05, -0.30 OpenVR Gamepad Orientierung: 0.00, 0.38, 0.00, 0.92

Fähigkeiten beim Verbinden prüfen

window.addEventListener('gamepadconnected', (event) => {
  const { gamepad } = event;
  if (!('pose' in gamepad) || !gamepad.pose) {
    console.log(`${gamepad.id}: keine Pose-Daten verfügbar`);
    return;
  }
  const { hasPosition, hasOrientation } = gamepad.pose;
  const typ = hasPosition && hasOrientation ? '6DoF'
    : hasOrientation ? '3DoF (nur Rotation)'
    : 'ohne Tracking';
  console.log(`${gamepad.id}: ${typ}`);
});
OpenVR Gamepad: 6DoF

Wurfgeschwindigkeit aus linearVelocity berechnen

const getThrowSpeed = (pad) => {
  const v = pad?.pose?.linearVelocity;
  if (!v) return null;
  const [x, y, z] = v;
  return Math.hypot(x, y, z); // m/s
};

const pad = navigator.getGamepads().find((p) => p?.pose);
const speed = pad ? getThrowSpeed(pad) : null;
console.log(speed !== null ? `Geschwindigkeit: ${speed.toFixed(2)} m/s` : 'Keine Geschwindigkeitsdaten');
Geschwindigkeit: 3.47 m/s

// Wichtig · Fallstricke

Veraltet und nicht standardisiert: GamepadPose gehört zu den WebVR-Erweiterungen der Gamepad API. Nur Firefox hat es umgesetzt, und das auch nur hinter dem Flag dom.gamepad.extensions.enabled. Chrome, Safari und Edge unterstützen es nicht. Für den Produktiveinsatz sollte man es nicht verwenden, sondern auf WebXR (XRInputSource, XRFrame.getPose()) umsteigen.

  • Vor dem Zugriff immer prüfen, ob gamepad.pose existiert, und die Vektor-Eigenschaften einzeln auf null testen.
  • hasPosition === false heißt: Das Gerät ist ein 3DoF-Controller, position ist dann null oder geschätzt.
  • Die zurückgegebenen Float32Array-Objekte sind Momentaufnahmen. Wer sie speichert, muss sie kopieren (Float32Array.from()), weil manche Implementierungen die Arrays wiederverwenden.
  • Die Gamepad API setzt einen sicheren Kontext (HTTPS) voraus. Außerdem liefert navigator.getGamepads() erst Daten, nachdem der Nutzer mit dem Gerät interagiert hat.