workshop
workshop copied to clipboard
Compass example has limited browser support
The compass example depends on the requestPermission method which currently has limited browser support. On other browsers/devices either no extra permissions are needed or a request is triggered by window.addEventListener('deviceorientation'). A more generic solution which maintains the existing structure might look like
if (window.DeviceOrientationEvent) {
locate.addEventListener('click', function () {
Promise.resolve(
typeof DeviceOrientationEvent.requestPermission === 'function'
? DeviceOrientationEvent.requestPermission()
: ''
)
I don't have that many different devices available. Do you? If so, would you mind testing this?
function initCompass() {
const compass = new Kompas();
compass.watch();
compass.on('heading', function (heading) {
style.getImage().setRotation((Math.PI / 180) * heading);
});
}
locate.addEventListener('click', function () {
if (
window.DeviceOrientationEvent &&
typeof DeviceOrientationEvent.requestPermission === 'function'
) {
DeviceOrientationEvent.requestPermission()
.then(initCompass)
.catch(function (error) {
alert(`ERROR: ${error.message}`);
});
} else {
initCompass();
}
});
That is almost the method I used to get it working on Android with Chrome - although I put the window.DeviceOrientationEvent check outside the whole block that was probably being over-cautious - the only browser which doesn't have DeviceOrientationEvent seems to be Safari for Mac. I don't have that but I don't think adding an listener for a non-existent event type causes errors on any browser?
Your proposed update certainly works with Chrome 99 Android 12 and also Chrome 81 Android 4.4

My application was using EPSG:27700. At the extremities there is a noticeable different between true and grid north and additional calculation is needed to align the compass correctly

smBottom = ol.proj.transform([point[0], point[1] - 100], viewProjection, 'EPSG:3857');
smTop = ol.proj.transform([point[0], point[1] + 100], viewProjection, 'EPSG:3857');
variation = Math.atan2(smBottom[0] - smTop[0], smTop[1] - smBottom[1]);
style.getImage().setRotation(variation + heading);