简体   繁体   中英

Mapbox GL JS Bearing

Is it possible in Mapbox GL JS to get the users bearing? I would like to show the direction in which the user is facing, to assist them in navigating to nearby POI. I understand that it is possible to set the bearing of the map and also get the current bearing of it, but i need the actual real life bearing of the user. Kind of the same thing as on Google Maps: 在此处输入图片说明

The service is intended to run as an Ionic app on iOS and Android, and the assistance in bearing is a key feature in helping them locate nearby POI on a well populated map.

You can get the user's bearing (if their device has such a sensor) by obtaining a Coordinates object from Gelocation#getCurrentPosition() and reading Coordinates#heading .

Mapbox GL JS has no built-in user interface for displaying a user's heading. Building your own user interface is easy. See this example which uses the symbol-rotation property .

So, after some time spend on this, i thought I'd show how i ended up doing this, in case someone else needs it or have a better solution.

It seems cordova has a built in "heading" property in the position object. https://github.com/apache/cordova-plugin-geolocation

var heading = $rootScope.position.heading;

First, i make sure that the marker is always pointing in the heading direction, even when the user turns the map, by subtracting the mapBearing(degrees the map has turned from North), from the user heading.

map.on('rotate', function(){
    map.setLayoutProperty('drone', 'icon-rotate', heading - map.getBearing())
});

I create an icon, at the users position, add the source and add the layer with the source.

map.on('load', function () {
  var point = {"type": "Point", "coordinates": [$rootScope.position.long, $rootScope.position.lat]};
  map.addSource('drone', {type: 'geojson', data: point });
  map.addLayer({
    "id": "drone",
    "type": "symbol",
    "source": "drone"
  }
});

Next i check that heading is actually available, since it only appears to return a value, when the user is moving(only tested on Android so far), and if it is, update the heading of the point.

if($rootScope.position.heading){
    var heading = $rootScope.position.heading; 
    map.setLayoutProperty('drone', 'icon-rotate', $rootScope.position.heading);
};

Finally i update the position of the point, in a "$watch" position.

map.getSource('drone').setData(point);

This way, i can watch the users heading, and the point keeps on track, even when the user rotates the map.

For the users coming here after 2020 (what an year lol), mapbox gl js now supports geolocation which not only provides user's heading but also a bunch of other helpful data:

const geolocate = map.addControl(
 new mapboxgl.GeolocateControl({
   positionOptions: {
      enableHighAccuracy: true
   },
   trackUserLocation: true
 })
)

then listen for geolocate event:

geolocate.on('geolocate', (e) => {
     console.log(e); 
});

this will give you following object:

{
coords: {
    accuracy: number;
    altitude: number;
    altitudeAccuracy: number;
    heading: number;
    latitude: number;
    longitude: number;
    speed: number;
  };
  timestamp: number;
 

heading will give you direction of the user. As the geolocate control keeps triggering automatically so can get the user's direction as well as speed and altitude etc in real time and use that to display data driven symbols on map.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM