Officially, since 2016, Chrome's DeviceOrientationEvent
doesn't and support absolute orientation:
Starting with Chrome 50, the degrees included in the
DeviceOrientationEvent are by default no longer absolute with respect
to the Earth’s coordinate frame. This means that
DeviceOrientationEvents should only be triggered when there’s actual
movement, as detected by some combination of a device’s accelerometer
and gyroscope. The magnetometer, and false readings due to magnetic
field fluctuations, are out of the picture.
Strangely, in practice it does work for iPhone's chrome, and you can use event.webkitCompassHeading
produce absolute orientation, while in Android it is relatively to the initial orientation while loading.
My solution is using DeviceOrientationAbsolute
(non-standard, and non-pretty):
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 (also works for web browser, not only Cordova).
Exampled here (in mobile)
UPDATE:
For completeness sake, as of ios13+, iphone demands asking permission only upon user gesture. Full code for ios+android:
on deviceready -
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);
}
}
upon user gesture -
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.")');
}
});
}