javascriptgeolocationleaflet

leaflet map: update marker using navigator.geolocation.watchPosition?


I'm trying to use a leaflet map to show the current position of the user on the map. Something like a live GPS tracking.

This is my current code:

  var watchID;
         var geoLoc;

         function showLocation(position) {
            var latitude = position.coords.latitude;
            var longitude = position.coords.longitude;
         }

         function errorHandler(err) {
            if(err.code == 1) {
               alert("Error: Access is denied!");
            }

            else if( err.code == 2) {
               alert("Error: Position is unavailable!");
            }
         }

         function getLocationUpdate(){
            if(navigator.geolocation){
               // timeout at 60000 milliseconds (60 seconds)
               var options = {timeout:60000};
               geoLoc = navigator.geolocation;
               watchID = geoLoc.watchPosition(showLocation, errorHandler, options);
                var map = L.map('map_2385853')

    googleStreets = L.tileLayer('http://{s}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}',{
    maxZoom: 20,
    subdomains:['mt0','mt1','mt2','mt3']
}).addTo(map);

      /*L.tileLayer('http://{s}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}', {
      attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://cloudmade.com">CloudMade</a>',
      maxZoom: 18
      }).addTo(map);*/

      map.locate({setView: true, maxZoom: 16});
      function onLocationFound(e) {
        var radius = e.accuracy / 2;
        L.marker(e.latlng).addTo(map)
            .bindPopup("You are within " + radius + " meters from this point").openPopup();
        L.circle(e.latlng, radius).addTo(map);
      }
      map.on('locationfound', onLocationFound);




            }

            else{
               alert("Sorry, browser does not support geolocation!");
            }
         }




getLocationUpdate();

This code only adds the marker once and doesn't do anything else with it (doesn't remove or add another) when the user's location changes.

I tried the above code on my mobile device and I can confirm that the marker only gets added once and stays there.

Could someone please advise on this?

HERE IS A WORKING FIDDLE:

https://jsfiddle.net/31ws6z37/

EDIT:

This is what i have so far. but I get the following error:

ERROR:

TypeError: map.removeLayer(...).bindPopup is not a function


map.removeLayer(marker)

CODE:

         function initializeMapAndLocator(){

                var map = L.map('map_2385853');


    googleStreets = L.tileLayer('http://{s}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}',{
    maxZoom: 20,
    subdomains:['mt0','mt1','mt2','mt3']
}).addTo(map);



           map.locate({setView: true, 
                       maxZoom: 16, 
                       watch:true, 
                       timeout: 60000
                      });

      function onLocationFound(e) {
        var radius = e.accuracy / 2;
        //L.marker(e.latlng).addTo(map)
        marker = new L.Marker(e.latlng, {draggable:true})
        map.addLayer(marker)
        map.removeLayer(marker)
            .bindPopup("You are within " + radius + " meters from this point").openPopup();
        L.circle(e.latlng, radius).addTo(map);
      }
      map.on('locationfound', onLocationFound);



         }

initializeMapAndLocator();

Solution

  • Hm it's not clear for me why you are using, two same methods for the same approach. You are using Geolocation.watchPosition() and map.locate(), which do fundamentally the same things. In this snippet Geolocation.watchPosition() has no purpose, it only call's showLocation(position), which just initialize two variables. The second method you are using is map.locate(), what should be your function of choice. Here you are doing right to add your marker, but regarding to the docs you have to set the watch option to true using map.locate() . You are going better to remove the Geolocation.watchPosition() and to it simply with map.locate():

    function initializeMapAndLocator(){
    
    var map = L.map('map_2385853')
    
    googleStreets = L.tileLayer('http://{s}.google.com/vt/lyrs=m&x={x}&y={y}&z={z}',{
            maxZoom: 20,
            subdomains:['mt0','mt1','mt2','mt3']
        }).addTo(map);
    
    
    
    map.locate({setView: true, 
                 maxZoom: 16, 
                 watch:true
               });
    
    function onLocationFound(e) {
        var radius = e.accuracy / 2;
        L.marker(e.latlng).addTo(map)
            .bindPopup("You are within " + radius + " meters from this point").openPopup();
        L.circle(e.latlng, radius).addTo(map);
    }
    
    map.on('locationfound', onLocationFound);
    
    }
    
    
    initializeMapAndLocator();
    

    Here goes a FIDDLE triggering locate and adding a marker with circle.