October 9, 2011
DeviceOrientation event and device orientation
I’ve been building an HTML5+JavaScript demo for using the device orientation and device motion events for an educational application. The article ”This End Up: Using Device Orientation & Device Motion” on HTML5 Rocks does a great job explaining how to work with these events. In my case, I’m controlling a ball based on the device orientation (you know, like in a labyrinth type game). This is easy to do with HTML5 device orientation events. So, what I do is register an event handler for the ondeviceorientation event:
window.addEventListener("deviceorientation", orientationHandler, false);
The handler simply stores the values from the event for later use:
function orientationHandler(eventData) {
tiltLR = eventData.gamma;
tiltFB = eventData.beta;
}
The gamma and beta attributes of the event object give the left-right and front-back rotation angles. Based on these values, the position of the ball can be updated (tiltLR is change of x-coordinate, tiltFB y). For the iPad, I’ve divided them by 3 to get a decent speed. Note, that I’m simplifying things here and not considering the fact that Firefox has an event of their own. Read the linked article for details.
Now all goes well until the user turns the phone/tablet on its side or upside down. Now the ball moves in weird directions. The simple fix to this (which I’m sure I’ll forget soon, hence the blogpost) is to check window.orientation and change the values accordingly. The value of window.orientation will be 0 when the device is in its’ normal orientation, -90 when rotated on its’ right side, 90 on left side and 180 when upside down. So, to take this into account and get the x and y coordinate changes:
var orient = window.orientation;
if (!orient || orient === 0) { // normal portrait orientation
dx = tiltLR;
dy = tiltFB;
} else if (orient === -90) { // landscape, rotated clockwise
dx = -tiltFB;
dy = tiltLR;
} else if (orient === 90) { // landscape, rotated counterclockwise
dx = tiltFB;
dy = -tiltLR;
} else if (orient === 180) { // portrait, upside down
dx = -tiltLR;
dy = -tiltFB;
}
This works and the ball moves in a natural way relative to the browser window. Still, it is difficult to control it when the window gets rotated. Eventually, I’d like to disable rotation of the browser window. Is there any way to do it with HTML/CSS/JS? Or is this one of those things that require wrapping the webapp into a native application?
Finally, my use case for this: I’m building an interactive exercise for learning the binary search tree search that uses the deviceorientation event. After testing this on iPad, I ran into the problem described. More on the exercise later :)