简体   繁体   中英

Detect phone rotation in Javascript Windows Phone mobile application

I am writing a mobile application for Windows Phone in HTML5. I want to detect the phone's rotation around the z-axis (I mean the rotation that is used for example in Doodle jump to make the character jump to the left or to the right).

In my application, a line that is vertical in the screen must remain vertical (absolute position in the real world) if I rotate the screen to the left or to the right. To accomplish this, I use the relative values of the angle: each time the screen is rotated a little, I rotate the points of the line by the same amount, but negative.

This works PERFECTLY if the phone is laying on a table or almost horizontal, but the behaviour is much less precise if for example I watch the phone in front of me. Anyway this is not a big problem of course because most users watch the phone from up to down, but a game like doodle jump behaves perfectly also in this situation.

Here is part of the code:

window.addEventListener("deviceorientation", handleOrientation, true);

function handleOrientation(event) {

    alphaDiff = Math.floor(event.alpha) - alphaOld;
    alphaOld = Math.floor(event.alpha);

    //Rotation of the vertical line (x1,y1) - (x2,y2) around the center of the screen

    var newPoint = rotate(225, 400, x1, y1, alphaDiff);

    x1 = newPoint[0];
    y1 = newPoint[1];

    newPoint = rotate(225, 400, x2, y2, alphaDiff);

    x2 = newPoint[0];
    y2 = newPoint[1];
}

function rotate(cx, cy, x, y, angle) {

    var radians = (Math.PI / 180) * angle;
    cos = Math.cos(radians);
    sin = Math.sin(radians);
    nx = (cos * (x - cx)) - (sin * (y - cy)) + cx;
    ny = (sin * (x - cx)) + (cos * (y - cy)) + cy;

    return [nx, ny];
}

Have you tried beta (for the x-axis) or gamma (for the y-axis)?

eg

function handleOrientation(event) {
    var absolute = event.absolute;
    var alpha    = event.alpha; // z-axis
    var beta     = event.beta;  // x-axis
    var gamma    = event.gamma; // y-axis

    // Do stuff with the new orientation data
}

Orientation Values Explained

The value reported for each axis indicates the amount of rotation around a given axis in reference to a standard coordinate frame.

  • The DeviceOrientationEvent.alpha value represents the motion of the device around the z-axis , represented in degrees with values ranging from 0 to 360 .
  • The DeviceOrientationEvent.beta value represents the motion of the device around the x-axis , represented in degrees with values ranging from -180 to 180 . This represents a front to back motion of the device.
  • The DeviceOrientationEvent.gamma value represents the motion of the device around the y-axis , represented in degrees with values ranging from -90 to 90 . This represents a left to right motion of the device.

说明


It also worth checking browser compatibility for this API.


As well as deviceorientation , you can check compassneedscalibration and devicemotion . For more details on deviceorientation see MDN .

A combination of beta and gamma seems to give pretty good results. Basically, I normalize the values to a specific range and get the ratio.

window.addEventListener("deviceorientation", function(event){
    var b = Math.abs(event.beta)/90;
    if(b>1) b = 2-b;

    var g = event.gamma/90;
    if(Math.abs(event.beta)>90) g = -g;

    var x = g/Math.max(0.25,b);
});

The final value is in x , positive means right, negative means left. It works with the phone held horizontally or at any angle facing you.

Update: To make the detection work in a vertical position, the code calculates how much the phone is leaning and to which direction. The value in x is always positive if the phone is leaning right and negative if leaning left.

This example shows a blue box in the middle of the screen and moves it to whichever direction the phone is leaning:

<!DOCTYPE html>
<html>
    <head><meta name="viewport" content="width=1000,user-scalable=no"/></head>
    <body style="margin:0">
        <pre id="log" style="font-size:4em;"></pre>
        <div id="box" style="background:#69c;width:100px;height:100px;position:relative;left:450px"></div>
        <script>
            var box = document.getElementById("box");
            var log = document.getElementById("log");
            var smoothx = 0;
            window.addEventListener("deviceorientation", function(event){
                var b = Math.abs(event.beta)/90;
                if(b>1) b = 2-b;

                var g = event.gamma/90;
                if(Math.abs(event.beta)>90) g = -g;

                var x = g/Math.max(0.25,b);
                smoothx = smoothx*0.7+x*0.3;

                box.style.left = Math.max(0, Math.min(900, smoothx*500+450))+"px";
                log.innerText = x.toFixed(1)+"\n"+smoothx.toFixed(1);
            });
        </script>
    </body>
</html>

Because the sensor seems to be very sensitive to movement, I implemented a simple smoothing that gives a steadier value in smoothx . Use x for immediate value without smoothing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM