JS Shake Detection Tutorial

Learn how to detect device motion without any libraries.

To detect a shake, we use the browser's devicemotion API. This tutorial covers the math, the iOS permission requirements, and the final implementation.

Step 1: The Math (Measuring G-Force)

The accelerometer provides values for X, Y, and Z axes. To detect a shake regardless of the phone's orientation, we calculate the total magnitude of the acceleration vector.

Formula: Magnitude = √(x² + y² + z²)

We use accelerationIncludingGravity. A stationary phone has a magnitude of roughly 9.8 (Earth's gravity). A shake usually produces a spike over 15 or 20.

Step 2: Handling iOS 13+ Permissions

Modern iPhones require the user to manually grant permission to use motion sensors. You cannot just start listening; you must trigger the request via a user interaction, like a button click.

function requestPermission() {
  if (typeof DeviceMotionEvent.requestPermission === 'function') {
    DeviceMotionEvent.requestPermission()
      .then(response => {
        if (response == 'granted') {
          window.addEventListener('devicemotion', handleMotion);
        }
      })
      .catch(console.error);
  } else {
    // Non-iOS devices don't need permission
    window.addEventListener('devicemotion', handleMotion);
  }
}

Step 3: The Shake Logic

We add a "Debounce" timer. Without this, a single physical shake might fire the code 50 times in one second. We force the code to wait (e.g., 1000ms) before detecting a new shake.

let lastShake = 0;
const MIN_INTERVAL = 1000; // Wait 1 sec between shakes

function handleMotion(event) {
  const acc = event.accelerationIncludingGravity;
  if (!acc) return;

  // Calculate Magnitude
  const total = Math.sqrt(acc.x**2 + acc.y**2 + acc.z**2);

  // Threshold of 15 is a good starting point
  if (total > 15) {
    const now = Date.now();
    if (now - lastShake > MIN_INTERVAL) {
      lastShake = now;
      alert("Shake Detected!"); 
    }
  }
}

Live Demo

Test the code right here. If you are on a mobile device, click the button below and shake your phone.

Status: Inactive