Search code examples
javascriptmobileorientation

Find if device is tilted left or right


I would like to find if a device, in landscape mode, is tilted left, right or not at all. Example:

Not at all:

enter image description here

Left:

enter image description here

Right:

enter image description here

I have looked at the deviceorientation API but found no clear way to find none, left or right. I would prefer to have it considered none if the phone is tilted only a small amount. It would be awesome if I could get a number for the rotation, positive if left, negative if right, 0 if none, but this is not required. I would also like a answer that has the most browser support possible.


Solution

  • The section "4.1 deviceorientation Event" of the DeviceOrientation Eventdraft says that

    Thus the angles alpha, beta and gamma form a set of intrinsic Tait-Bryan angles of type Z-X'-Y''.

    AFAIU, what you want is convert that to Z-X'-Z'' instrinsic Euler angels and get the angle that represents the last rotation. Well, let's dust off 3D trigonometric skills and with help from quite useful table in the Wikipedia we can see that

    spin = atan2(cos(beta)*sin(gamma), sin(beta))
    

    or if we put it into some JS code

    window.addEventListener("deviceorientation", handleOrientation, true);
    function handleOrientation(event) {
        // those angles are in degrees
        var alpha = event.alpha;  
        var beta = event.beta;
        var gamma = event.gamma;
    
        // JS math works in radians
        var betaR = beta / 180 * Math.PI;
        var gammaR = gamma / 180 * Math.PI;
        var spinR = Math.atan2(Math.cos(betaR) * Math.sin(gammaR), Math.sin(betaR));
    
        // convert back to degrees
        var spin = spinR * 180 / Math.PI;
    }
    

    Note that calculated as such spin is 0 when the device is in natural portrait orientation. And your landscape example corresponds to -90 degrees.

    smartphone in "left" landscape orientation

    Beware also that Orientation and motion data explained MDN page says that

    Warning: Currently, Firefox and Chrome do not handle these coordinates the same way. Take heed when using them.

    I tested my code only on iOS in Chrome. You can see a live demo at https://plnkr.co/edit/78IAUlbkQZMmogdlxGAH?p=preview. Note that you need to click on an icon "Launch the preview in a separate window" in the top-right of the preview area or it won't work because access to the deviceorientation API from iframe is prohibit at least on iOS.