mapbox / mapbox-gl-js

Interactive, thoroughly customizable maps in the browser, powered by vector tiles and WebGL
https://docs.mapbox.com/mapbox-gl-js/
Other
11.2k stars 2.22k forks source link

Add heading to GeolocateControl #8329

Closed Plantain closed 3 years ago

Plantain commented 5 years ago

Motivation

Navigating yourself from a map with only position is difficult, showing a direction indicator or compass heading makes it much easier. Most modern mobile devices have a compass built in. Google Maps supports it.

Design

map.addControl(new mapboxgl.GeolocateControl({ positionOptions: { enableHighAccuracy: true }, fitBoundsOptions: { maxZoom:7, }, trackUserLocation: true trackUserHeading: true <---- }), 'bottom-left');

Mock-Up

Example from Google Maps, see the direction arrow pointing out of the blue dot. xbZ8a

andrewharvey commented 5 years ago

@Plantain Do you have a good summary of the browser support for this? My understanding is browser support is not standardised and patchy.

Need absolute compass, not just relative bearing (it seems some browsers may only support the latter?).

See also https://ai.github.io/compass.js/ and https://stackoverflow.com/questions/16048514/can-i-use-javascript-to-get-the-compass-heading-for-ios-and-android.

Google Maps is a native app which has better APIs for access to this, and while most modern devices may have a compass, you mightn't always be able to access that though the browser.

andrewharvey commented 5 years ago

See also some background at #3781, the original design was to include the bearing.

Plantain commented 5 years ago

My understanding is it works on FF/Chrome via DeviceOrientation (it does require the users compass to already be calibrated), and it works on Safari via webkitCompassHeading.

andrewharvey commented 5 years ago

My understanding is it works on FF/Chrome via DeviceOrientation (it does require the users compass to already be calibrated), and it works on Safari via webkitCompassHeading.

Yeah I was just reading up on this now. It's not standard across browsers, but looks like we can support on Chrome and Safari separately.

I'd been keen to help review a PR which implemented this if you wanted to have a go.

douglasg14b commented 2 years ago

@tsuz Has this been released? I'm noticing this doesn't work, neither on a phone, or when using Chrome's devtools sensors.

Using v2.6.1

douglasg14b commented 2 years ago

After some debugging it looks like this may be the problem:

        const addListener = () => {
            if ('ondeviceorientationabsolute' in window) {
                window.addEventListener('deviceorientationabsolute', this._onDeviceOrientationListener);
            } else {
                window.addEventListener('deviceorientation', this._onDeviceOrientationListener);
            }
        };

deviceorientationabsolute seems to only fire once, but deviceorientation fires whenever the orientation changes. But if deviceorientationabsolute exists, then that's used instead of deviceorientation.

The absolute event is also non-standard by the looks of it? https://developer.mozilla.org/en-US/docs/Web/API/Window/ondeviceorientationabsolute