官方,since 2016,Chrome 的DeviceOrientationEvent 不支持绝对方向:
从 Chrome 50 开始,包含在
DeviceOrientationEvent 在默认情况下不再是绝对的
到地球的坐标系。这意味着
DeviceOrientationEvents 应该只在实际存在时触发
运动,由设备的加速度计的某种组合检测到
和陀螺仪。磁力计,以及由于磁力造成的错误读数
场波动,不在画面中。
奇怪的是,实际上它确实适用于 iPhone 的 chrome,你可以使用 event.webkitCompassHeading 产生绝对方向,而在 Android 中它是相对于加载时的初始方向。
我的解决方案是使用DeviceOrientationAbsolute(non-standard,不漂亮):
if (isiOS) {
window.addEventListener('deviceorientation', manageCompass)
} else if (isAndroid) {
window.addEventListener("deviceorientationabsolute", manageCompass, true);
}
function manageCompass(event) {
if (event.webkitCompassHeading) {
absoluteHeading = event.webkitCompassHeading + 180;
} else {
absoluteHeading = 180 - event.alpha;
}
console.log(absoluteHeading);
}
Another helpful answer(也适用于网络浏览器,不仅仅是 Cordova)。
Exampled here(移动端)
更新:
为了完整起见,从 ios13+ 开始,iphone 仅在用户手势时才要求请求许可。 ios+android完整代码:
设备就绪 -
TrackOrientation() {
// starts tracking on deviceready, updates value on currentCompass$ (fallback for ios13+ at "compassPremissioniOS13" funtion)
if (typeof DeviceOrientationEvent['requestPermission'] !== 'function') {
const deviceOrientationLestener = (event) => {
if (this.globals.iphone) {
this.currentCompass$.next(event['webkitCompassHeading']);
} else {
if (event.absolute) {
this.currentCompass$.next(360 - event.alpha);
} else {
window.removeEventListener('deviceorientation', deviceOrientationLestener);
window.addEventListener('deviceorientationabsolute', (eventB) => {
this.currentCompass$.next(360 - eventB['alpha']);
}, true);
}
}
};
window.addEventListener('deviceorientation', deviceOrientationLestener);
}
}
根据用户手势 -
compassPremissioniOS13$() {
return new Promise((resolve, reject) => {
if (navigator.geolocation) {
if (typeof DeviceOrientationEvent['requestPermission'] === 'function') {
DeviceOrientationEvent['requestPermission']()
.then(permissionState => {
if (permissionState === 'granted') {
window.addEventListener('deviceorientation', (event) => {
this.currentCompass$.next(event['webkitCompassHeading']);
});
resolve('User accepted');
} else {
reject('User declined');
}
})
.catch(console.error);
}
} else {
alert('deviceorientation is not supported by this browser.');
this.sendError('deviceorientation = null ("deviceorientation is not supported by this browser.")');
}
});
}