0
votes

I use Mapbox to show on map the path that the user traveled (with my app on phone). My application saves the GPS position regularly, which I then show on the map with the help of Mapbox GL.

  <script>
            mapboxgl.accessToken = 'pk.XXX';
            var map = new mapboxgl.Map({
                container: 'map', 
                style: 'mapbox://styles/mapbox/streets-v11',
                center: [aa.AAA, bb.BBB], 
                zoom: 18
            });
            var popup = new mapboxgl.Popup()
                    .setText("XXX YYY")
                    .addTo(map);
            var marker = new mapboxgl.Marker()
                    .setLngLat([aa.AAA, bb.BBB])
                    .addTo(map)
                    .setPopup(popup);

            map.on('load', function () {
                map.addSource('route', {
                    'type': 'geojson',
                    'data': {
                        'type': 'Feature',
                        'properties': {},
                        'geometry': {
                            'type': 'LineString',
                            'coordinates': [
    [xx.XXX,yy.YYY],
[xx.XXX,yy.YYY],
[xx.XXX,yy.YYY]

                        }
                    }
                });
                map.addLayer({
                    'id': 'route',
                    'type': 'line',
                    'source': 'route',
                    'layout': {
                        'line-join': 'round',
                        'line-cap': 'round'
                    },
                    'paint': {
                        'line-color': '#888',
                        'line-width': 8
                    }
                });
            });

        </script>

I would like Mapbox to snap the position to the road on the map. Something like "snap-to-road" in Google Maps.

I know that Mapbox has something called "map matching". Only I want to list many intermediate points (not just the beginning and the end), and I would like everyone with them to be snaped to the road on the map.

Is something like this possible? Maybe there are some other mapping solutions that can do that?

1
docs.mapbox.com/api/navigation/#map-matching: "A semicolon-separated list of {longitude},{latitude} coordinate pairs to visit in order. There can be between 2 and 100 coordinates." - Anatoly Sukhanov

1 Answers

0
votes

Take a look at my solution below. It uses Mapbox map matching, then extracts the tracepoints from the response object and draws them on the map.

To make it work on your end, just replace <ACCESS_TOKEN> with your Mapbox access token.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Map Matched Coordinates</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://api.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css" rel="stylesheet" />
<style>
    body { margin: 0; padding: 0; }
    #map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<script>
    mapboxgl.accessToken = '<ACCESS_TOKEN>';
    var map = new mapboxgl.Map({
        container: 'map',
        style: 'mapbox://styles/mapbox/streets-v11',
        center: [-117.17292,32.71256],
        zoom: 15
    });

    map.on('load', function () {
    
    
    
        // map matching request

    var matched_coordinates = [];
        
        // Create
        let xhr = new XMLHttpRequest();

        // GET REQUEST
        xhr.open('GET', 'https://api.mapbox.com/matching/v5/mapbox/driving/' + 
    '-117.17282,32.71204;-117.17288,32.71225;-117.17293,32.71244;-117.17292,32.71256;-117.17298,32.712603;-117.17314,32.71259;-117.17334,32.71254' + 
    '?access_token=<ACCESS_TOKEN>' +
    '&geometries=geojson');

        // After Response is received
        xhr.onload = function() {
          
            if (xhr.status != 200) {
              // NOT SUCCESSFUL
            } else {
              // SUCCESSFUL
        var response = JSON.parse(xhr.response);
        var tracepoints = response["tracepoints"];

        for(var i = 0; i < tracepoints.length; i++){

          matched_coordinates.push(tracepoints[i]["location"]);



        }


        map.addSource('route', {
            'type': 'geojson',
            'data': {
                'type': 'Feature',
                'properties': {},
                'geometry': {
                    'type': 'LineString',
                    'coordinates': matched_coordinates
                    
                }
            }
        });
        map.addLayer({
            'id': 'route',
            'type': 'line',
            'source': 'route',
            'layout': {
                'line-join': 'round',
                'line-cap': 'round'
            },
            'paint': {
                'line-color': '#888',
                'line-width': 8
            }
        });

            }
          
        }


    xhr.send();

    });
</script>

</body>
</html>