简体   繁体   English

在Javascript Windows Phone移动应用程序中检测手机轮换

[英]Detect phone rotation in Javascript Windows Phone mobile application

I am writing a mobile application for Windows Phone in HTML5. 我正在用HTML5编写Windows Phone的移动应用程序。 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). 我想检测手机围绕z轴的旋转(我的意思是旋转,例如在涂鸦跳转中使角色向左或向右跳跃)。

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)? 您是否尝试过beta (针对x轴)或gamma (针对y轴)?

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 . DeviceOrientationEvent.alpha值表示设备围绕z轴的运动,以度为单位,值范围为0360
  • The DeviceOrientationEvent.beta value represents the motion of the device around the x-axis , represented in degrees with values ranging from -180 to 180 . DeviceOrientationEvent.beta值表示设备围绕x轴的运动,以度为单位,值范围为-180180 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 . DeviceOrientationEvent.gamma值表示设备围绕y轴的运动,以度为单位,值范围为-9090 This represents a left to right motion of the device. 这表示设备从左到右的运动。

说明


It also worth checking browser compatibility for this API. 还值得检查此API的浏览器兼容性


As well as deviceorientation , you can check compassneedscalibration and devicemotion . 除了设备deviceorientation ,您还可以检查compassneedscalibration和设备devicemotion For more details on deviceorientation see MDN . 有关deviceorientation更多详细信息,请参阅MDN

A combination of beta and gamma seems to give pretty good results. betagamma组合似乎给出了相当不错的结果。 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. 最终值为x ,正数表示右,负表示左。 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. 如果手机向右倾斜,则x的值始终为正,如果向左倾斜,则x为负值。

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 . 因为传感器似乎对运动非常敏感,所以我实现了一个简单的平滑处理,在smoothx中提供了更稳定的值。 Use x for immediate value without smoothing. 使用x作为立即值而不进行平滑处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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