设备定向指南针Android

ca1c2owp  于 2023-03-21  发布在  Android
关注(0)|答案(3)|浏览(190)

我尝试使用deviceorientation事件实现一个指南针。我想使用rotation来旋转一个面向观察方向的箭头。我只是在deviceorientation改变时旋转Image。
在iOS上,通过执行以下操作,这就像charm一样有效:

if (typeof DeviceOrientationEvent.requestPermission === "function") {
          //@ts-ignore
          DeviceOrientationEvent.requestPermission()
            .then(permissionState => {
              if (permissionState === "granted") {
                this.compassActive = true;
                window.addEventListener(
                  "deviceorientation",
                  eventData =>
                    this.zone.run(() => {
                      if(!this.compassActive){
                        return false;
                      }
                      //@ts-ignore
                      this.rotatePlayerIcon(eventData.webkitCompassHeading);

                    }),
                  false
                );
              }
            })
            .catch(console.error);

因为DeviceOrientationEvent.webkitCompassHeading给了我一个基于顺时针世界的设备旋转演示。
我在Android上尝试了同样的方法,但是我找不到一个基于世界的解决方案。webkitCompassHeading在Android上不存在,所以我试着只使用eventData.alpha。但是这会根据事件触发时的旋转而不是根据世界北方给出0。
我发现所有的指南似乎都过时了。
如何在Android上获得像iOS上一样的顺时针指南针?

kuhbmx9i

kuhbmx9i1#

bellow youll see a compass of vtm-mapsforge. it also included a arrow. appart from the usually magnetometer-accelerometer sensor我建议使用定位轴承作为传感器是不是在所有准确的,很容易被打乱.关于指南针的好事情是,它包括代码,使它顺利旋转作为原始输出从传感器往往是嘈杂的.
对于Java代码,请查看this,它是vtm-mapsforge指南针的原始版本

pcww981p

pcww981p2#

问题是alpha不是绝对的,意味着0不是北方,而是0是设备在激活时指向的地方。
修复基于Chrome浏览器的最佳方法是使用W3C Generic Sensor API polyfills.Github中的AbsoluteOrientationSensor,就像大多数标准Android浏览器一样
我使用它的项目是基于Typescript的。下面是一个Typescript示例:

import {AbsoluteOrientationSensor} from 'motion-sensors-polyfill'

const options = { frequency: 60, referenceFrame: 'device' };
        const sensor = new AbsoluteOrientationSensor(options);
        sensor.addEventListener('reading', e => {
          this.zone.run(() => {
            var q = e.target.quaternion;
            let alpha = Math.atan2(2*q[0]*q[1] + 2*q[2]*q[3], 1 - 2*q[1]*q[1] - 2*q[2]*q[2])*(180/Math.PI);
            if(alpha < 0) alpha = 360+ alpha;
            this.alpha = 360 - alpha;
            this.rotatePlayerIcon(360 - alpha)
          })
        });
        sensor.start();
bcs8qyzn

bcs8qyzn3#

由绝对α、β和γ计算罗经航向的公式如下:

compass = -(alpha + beta * gamma / 90);
compass -= Math.floor(compass / 360) * 360; // Wrap to range [0,360]

上述公式对于零beta和gamma(例如,电话躺在table上)表现良好,并且对于beta=90(例如,保持直立)也有效。
现在是2023年,iOS仍然不支持绝对DeviceOrientationEvent,Android仍然不直接支持指南针,下面的TypeScript代码展示了如何获取两种类型设备的指南针值,你可以通过移除冒号后面的类型说明符将其转换为JavaScript。

function startCompassListener(callback: (compass: number) => void) {
    if (!window["DeviceOrientationEvent"]) {
        console.warn("DeviceOrientation API not available");
        return;
    }
    let absoluteListener = (e: DeviceOrientationEvent) => {
        if (!e.absolute || e.alpha == null || e.beta == null || e.gamma == null)
            return;
        let compass = -(e.alpha + e.beta * e.gamma / 90);
        compass -= Math.floor(compass / 360) * 360; // Wrap into range [0,360].
        window.removeEventListener("deviceorientation", webkitListener);
        callback(compass);
    };
    let webkitListener = (e) => {
        let compass = e.webkitCompassHeading;
        if (compass!=null && !isNaN(compass)) {
            callback(compass);
            window.removeEventListener("deviceorientationabsolute", absoluteListener);
        }
    }

    function addListeners() {
        // Add both listeners, and if either succeeds then remove the other one.
        window.addEventListener("deviceorientationabsolute", absoluteListener);
        window.addEventListener("deviceorientation", webkitListener);
    }

    if (typeof (DeviceOrientationEvent["requestPermission"]) === "function") {
        DeviceOrientationEvent["requestPermission"]()
            .then(response => {
                if (response == "granted") {
                    addListeners();
                } else
                    console.warn("Permission for DeviceMotionEvent not granted");
            });
    } else
        addListeners();
}

测试时,我发现我的Android的绝对(α,β,γ)是非常不准确的(约60度误差α).然而,通过滚动设备周围校准自己,并得到了约5度误差.

相关问题