Christian Cantrell, Adobe's Air Product Manager and Evangelist, has released a video to demo websites that take advantage of the motion sensors in a mobile phone, tablet, or laptop via JavaScript. Now, let's take a look through the code and break down the core pieces that you'll need in order to build your own sites that can determine the 2-axis tilt, 3-axis gyroscope, and compass direction of the mobile device it's being displayed on.
Let's See It in Action
First, check out the video Christian put up to demo the functionality using the accelerometer on a MacBook Pro, as well as the compass on an iPad. The same functionality is present in the latest Android browser, as well (though it's not shown in the video).
Try the Demos Yourself
You can try out each of the demos yourself here:
Digging into the Code
To see the full source code, just right-click and hit view-source on either of the demos. For now, let's break down the pieces that actually react to the motion coordinates.
The window.ondeviceorientation Event
The heart of the motion controls is in the window.ondeviceorientation event. It is partially supported in Firefox (using the MozOrientation event), Google Chrome (as of version 7.0), iOS Safari (5.0+), Opera Mobile (12.0+), and Android (4.0+). IE9 does not support it and IE10 support is still unknown.
Listen for the Event
To be updated each time the device orientation changes, let's create an empty object. You must listen for the "deviceorientation" event using the following line of code:
window.addEventListener('deviceorientation', onDeviceOrientationChange, false);
Track the Current Device Orientation
To keep track of the current orientation, let's create an empty object and call it lastOrientation to hold the state. We can then add our onDeviceOrientationChange event handler to capture the event each time it fires, and update our lastOrientation object with the new state:
var lastOrientation = {};
function onDeviceOrientationChange(event) {
lastOrientation.gamma = event.gamma;
lastOrientation.beta = event.beta;
if (event.webkitCompassHeading != undefined) {
lastOrientation.currentHeading = (360 - event.webkitCompassHeading);
} else if (event.alpha != null) {
lastOrientation.currentHeading = (270 - event.alpha) * -1;
} else {
lastOrientation.currentHeading = null;
}
};
- The gamma property of the event will give you the horizontal orientation (or x-axis).
- The beta property of the event will give you the vertical orientation (or y-axis).
- The compass heading is different depending on the browser, as it hasn't been standardized yet. To keep things simple here, we've normalized the value and stored it in a property that we'll call currentHeading. Keep in mind, not all devices support a compass heading, so if it's not available, that value will be null.
Do Whatever You Want with the Orientation
By this point, you can now depend on your lastOrientation variable always being up to date with the current device orientation. Instead of updating your display every single time the orientation changes (this can be hundreds of times a second), it's more efficient to set an interval to execute your redrawing code a few times a second to achieve a decent frame rate. Use the following template to execute whatever code you want to with the gamma, beta, and currentHeading properties at about 30 frames per second:
setInterval(function() {
// Write whatever code you want to here to do anything you like with the coordinates.
// For example, this code will update a div with ID "output" to display the coordinates:
var sOut = 'gamma: ' + lastOrientation.gamma +
'
beta: ' + lastOrientation.beta +
'
currentHeading: ' + lastOrientation.currentHeading;
document.getElementById('output').innerHTML = sOut;
},33);
Have any questions? Let us know in the comments. For bonus points, can any of you share with the community how to track the delta of the changes in orientation between frames?
Hint: Christian does this in his demos. If you view the source and follow along, you should be able to figure it out.
Comments
No Comments Exist
Be the first, drop a comment!