设备方向罗盘 Android

DeviceOrientation Compass Android

我尝试使用 deviceorientation 事件实现一个指南针。我想使用旋转来旋转面向观察方向的箭头。我只是在 deviceorientation 更改时旋转图像。

在 iOS 上,通过执行以下操作就像魅力一样:

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,而不是基于世界北方。

我找到的所有指南似乎都已过时。

如何像在 iOS 上一样在 android 上获得顺时针罗盘?

在下面你会看到一个 vtm-mapsforge 的指南针。它还包括一个箭头。与通常的磁力计-加速度计传感器不同,我建议使用方位角,因为传感器一点也不准确,而且很容易获得 disrupted.the 罗盘的好处是它包含代码,可以使其作为原始输出平稳旋转传感器通常很吵。

Java代码看this,是vtm-mapsforge指南针的原版

问题是 alpha 不是绝对的,这意味着 0 不是北方,而是 0 是设备在激活时指向的位置。

修复基于 chrome 的浏览器的最佳方法,就像大多数标准 Android 浏览器一样,使用来自 W3C 通用传感器 API polyfill 的 AbsoluteOrientationSensor。 Github

我使用它的项目是基于 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();