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.
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.
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.
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);
}
}
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!");
}
}
}
Test the code right here. If you are on a mobile device, click the button below and shake your phone.