我正在尝试使用Javascript / JQuery(使用deviceorientation)创建可靠的指南针,以便它可在iOS和Android移动设备上使用。我在Stackoverflow中几乎了解每个与这个主题相关的问题(很古老)。我创建了一个非常简单的指南针,可以在iOS设备上正常工作。在Android设备(Galaxy S8)上,我有一个奇怪的行为:就像每天进行测试一样,北向指南针方向偏移了-45 / + 45、90(北向东),180(北向南) )或270度(北在西)。是的,我考虑过指南针校准(8位数字的运动,在测试之前将移动台绕其3轴旋转)。
这是指南针的Java代码:
if (isIos()) // // Function in the background evaluating OS
{
window.addEventListener('deviceorientation', function(event) {
var alpha;
// Use Webkit heading for iOS
alpha = event.webkitCompassHeading;
if (alpha < 0) { alpha += 360; }
if (alpha > 360) { alpha -= 360; }
// Calculated heading
console.log (alpha);
});
}
else {
// Any other device, with Chrome browser
if ('ondeviceorientationabsolute' in window) {
// Chrome 50+ specific
window.addEventListener('deviceorientationabsolute', function (event) {
var alpha = 360 - event.alpha;
if (alpha < 0) { alpha += 360; }
if (alpha > 360) { alpha -= 360; }
// Calculated heading
console.log (alpha);
});
}
else {
window.addEventListener('deviceorientation', function (event) {
var alpha = 180 - event.alpha;
if (alpha < 0) {
alpha += 360;
}
if (alpha > 360) {
alpha -= 360;
}
// Calculated heading
console.log (alpha);
});
}
}
简而言之:
我知道我还必须考虑beta和gamma轴。对于我的测试,我将手机放在桌子上,因此只有Alpha是相关的。
通过我的研究,我发现Stackoverflow(fulltilt-min.js)中提到的一个非常高级/完整的JavaScript指南针,考虑了所有3个轴。这是它的demo。甚至这个指南针也向我显示了与指南针完全相同的错误方向。
所以有人可以在Android手机上解释此行为,还是知道如何解决此问题?
问题是您的Alpha不是绝对的,意味着0不是北,而0是设备指向激活的位置。
修复基于chrome的浏览器的最佳方法,例如大多数标准的Android浏览器,都使用W3C Generic Sensor API polyfills中的AbsoluteOrientationSensor。Github
我在其中使用的项目基于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() if you are using an Angular Project to run it in the context of the component.
//If you using plain Javascript, you don't need this
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.rotateCompassClockwise(360 - alpha)
})
});
sensor.start();