如何在 Javascript 中为 iOS 和 Android 创建一个可靠的指南针?
How do I create a reliable compass for iOS and Android in Javascript?
我正在尝试在 Javascript/JQuery 中创建一个可靠的指南针(使用设备方向),以便它在 iOS 和 Android 移动设备上工作。
我几乎知道 Whosebug 中关于此主题的每个(非常老的)question/answer。我创建了一个非常简单的指南针,可以在 iOS 设备上正常工作。在 Android 设备 (Galaxy S8) 上,我有一个奇怪的行为:就像我每天测试它一样,罗盘方向 North 切换偏移量为 -45/+45、90(北方在东方)、180(北在南)或 270 度(北在西)。是的,我考虑过罗盘校准(8 位数运动,在测试前将手机绕其 3 个轴转动)。
这是罗盘的 Javascript 代码:
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);
});
}
}
简而言之:
- iOS (iPhone, iPad): 使用 event.webkitCompassHeading -> 工作正常
- Chrome: 使用ondeviceorientationabsolute -> 导致描述偏差问题
- 否则:考虑 alpha 的设备方向 -> 导致描述的偏差问题
我知道我还必须考虑 beta 和 gamma 轴。对于我的测试,我将手机置于 table,因此只有 alpha 是相关的。
通过我的研究,我发现了一个非常 advanced/complete javascript 中提到的 Whosebug (fulltilt-min.js) considering all 3 axes. Here's the demo 指南针。即使是这个指南针也向我显示了与我的指南针完全相同的错误航向。
那么谁能解释 Android 手机上的这种行为或知道如何解决这个问题?
问题是您的 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() 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.rotateCompassClockwise(360 - alpha)
})
});
sensor.start();
我正在尝试在 Javascript/JQuery 中创建一个可靠的指南针(使用设备方向),以便它在 iOS 和 Android 移动设备上工作。 我几乎知道 Whosebug 中关于此主题的每个(非常老的)question/answer。我创建了一个非常简单的指南针,可以在 iOS 设备上正常工作。在 Android 设备 (Galaxy S8) 上,我有一个奇怪的行为:就像我每天测试它一样,罗盘方向 North 切换偏移量为 -45/+45、90(北方在东方)、180(北在南)或 270 度(北在西)。是的,我考虑过罗盘校准(8 位数运动,在测试前将手机绕其 3 个轴转动)。
这是罗盘的 Javascript 代码:
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);
});
}
}
简而言之:
- iOS (iPhone, iPad): 使用 event.webkitCompassHeading -> 工作正常
- Chrome: 使用ondeviceorientationabsolute -> 导致描述偏差问题
- 否则:考虑 alpha 的设备方向 -> 导致描述的偏差问题
我知道我还必须考虑 beta 和 gamma 轴。对于我的测试,我将手机置于 table,因此只有 alpha 是相关的。
通过我的研究,我发现了一个非常 advanced/complete javascript 中提到的 Whosebug (fulltilt-min.js) considering all 3 axes. Here's the demo 指南针。即使是这个指南针也向我显示了与我的指南针完全相同的错误航向。
那么谁能解释 Android 手机上的这种行为或知道如何解决这个问题?
问题是您的 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() 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.rotateCompassClockwise(360 - alpha)
})
});
sensor.start();