Device Motion

This controller listens to devicemotion events from the Device Motion API and emits a normalized updated event containing acceleration, acceleration including gravity, rotation rate, and sampling interval. It also manages the permission flow when required.

Usage

<div {{ stimulus_controller('@pwa/device-motion') }}>
  <p id="motion-status">Waiting for motion data…</p>
</div>

<script type="module">
  const host = document.querySelector('[data-controller="pwa__device-motion"]');
  const out = document.getElementById('motion-status');

  host.addEventListener('device-motion:unavailable', () => {
    out.textContent = 'Device Motion API is not available on this device/browser.';
  });

  host.addEventListener('device-motion:permission-granted', () => {
    out.textContent = 'Permission granted. Receiving motion data…';
  });

  host.addEventListener('device-motion:permission-denied', () => {
    out.textContent = 'Permission denied. Cannot access motion sensors.';
  });

  host.addEventListener('device-motion:updated', (e) => {
    const { acceleration, rotationRate, interval } = e.detail;
    out.textContent =
      `Acc: x=${acceleration.x?.toFixed(2)} y=${acceleration.y?.toFixed(2)} z=${acceleration.z?.toFixed(2)} | ` +
      `Rot: α=${rotationRate.alpha?.toFixed(1)} β=${rotationRate.beta?.toFixed(1)} γ=${rotationRate.gamma?.toFixed(1)} | ` +
      `dt=${interval}ms`;
  });
</script>

Parameters

throttleValue: Intended to control how often updated events are dispatched to avoid spamming the UI.

Actions

None

Targets

None

Events

unavailable: the feature is not supported by the device.

permission-granted: permission prompt was granted; listener is attached.

permission-denied: User denied permission, or an error occurred during the permission request.

updated: On every device motion event (as delivered by the browser).

Contains the following object:

{
  acceleration: {
    x: number | null,
    y: number | null,
    z: number | null
  },
  accelerationIncludingGravity: {
    x: number | null,
    y: number | null,
    z: number | null
  },
  rotationRate: {
    alpha: number | null, // deg/s around Z
    beta: number | null,  // deg/s around X
    gamma: number | null  // deg/s around Y
  },
  interval: number // ms between samples
}

Last updated

Was this helpful?