JavaScript “shake” event in Mobile Safari

Apple released iOS 4.2 last week which contains an updated version of Mobile Safari. The list of enhancements include increased support for HTML5, the WebSockets API, and, of particular interest to this post, the DeviceMotionEvent and DeviceOrientationEvent JavaScript APIs.

Taking a look at the DeviceMotionEvent Class Reference, you see that this is a new event API which provides the ability to detect when a “significant change in motion occurs,” allowing JavaScript to take advantage of the accelerometer present in newer mobile devices. This is huge, because it brings the mobile web one step closer towards native functionality.

One of the interesting ways that native applications can take advantage of the accelerometer is to trigger a JavaScript event which happens when users “shake” their phones (or other devices). I thought it would be interesting to see if similar functionality could be implemented using the DeviceMotionEvent API, and was able to get a basic implementation working with the following code:

if (typeof window.DeviceMotionEvent != 'undefined') {
	// Shake sensitivity (a lower number is more)
	var sensitivity = 20;

	// Position variables
	var x1 = 0, y1 = 0, z1 = 0, x2 = 0, y2 = 0, z2 = 0;

	// Listen to motion events and update the position
	window.addEventListener('devicemotion', function (e) {
		x1 = e.accelerationIncludingGravity.x;
		y1 = e.accelerationIncludingGravity.y;
		z1 = e.accelerationIncludingGravity.z;
	}, false);

	// Periodically check the position and fire
	// if the change is greater than the sensitivity
	setInterval(function () {
		var change = Math.abs(x1-x2+y1-y2+z1-z2);

		if (change > sensitivity) {
			alert('Shake!');
		}

		// Update new position
		x2 = x1;
		y2 = y1;
		z2 = z1;
	}, 150);
}

As you can see, a JavaScript event is setup to update the position when the device moves and, once it does, the new position is calculated against the old to determine if the shake event should be fired. If you’re reading this and are using Mobile Safari with iOS 4.2 you can see it in action on the demo page.

I have plans to create a richer, more complete example of this soon, but in the meantime just this basic example gets me excited. Device aware functionality like this is a great step for the mobile web!