Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

set leaflet.js map to display current location

I am working with the leaflet.js package for meteor and I am having trouble getting the map to default to my current location on the initial render. The setView method works fine with hard numbers but it doesn't like my variables. I am pretty new to js so maybe the mistake is obvious. Here's what i have:

 Template.map.rendered = function() {
 L.Icon.Default.imagePath = 'packages/bevanhunt_leaflet/images';

 if (navigator.geolocation) {
  navigator.geolocation.getCurrentPosition(function(position) {
    console.log('--- Your Position: ---');
    console.log('Lat: ' + position.coords.latitude);
    latit = position.coords.latitude;
    console.log('Long: ' + position.coords.longitude);
    longit = position.coords.longitude;
    console.log('---------------------');
    var abc = L.marker([position.coords.latitude, position.coords.longitude]).addTo(map);
} 
)}

map = L.map('map', {
  doubleClickZoom: false
}).setView([latit, longit], 13);

The error i keep getting is

Uncaught TypeError: Cannot read property 'addLayer' of undefined
L.Marker.L.Class.extend.addTo @ leaflet-src.js:3511
(anonymous function) @ client.js?ea76789cca0ff64d5985320ec2127d5de1fb802f:28

when i console.log(latit) or console.log(longit) it returns the number, as well as "undefined" after it. Thanks in advance to anyone who can help with this!

EDIT:

exact console output on initial render:

Exception from Tracker afterFlush function:
debug.js:41 ReferenceError: latit is not defined
    at Template.map.rendered (client.js?    ea76789cca0ff64d5985320ec2127d5de1fb802f:36)
    at template.js:116
    at Function.Template._withTemplateInstanceFunc (template.js:437)
    at fireCallbacks (template.js:112)
    at null.<anonymous> (template.js:205)
    at view.js:104
    at Object.Blaze._withCurrentView (view.js:523)
    at view.js:103
at Object.Tracker._runFlush (tracker.js:468)
at onGlobalMessage (setimmediate.js:102)
client.js?ea76789cca0ff64d5985320ec2127d5de1fb802f:22 --- Your Position: ---
client.js?ea76789cca0ff64d5985320ec2127d5de1fb802f:23 Lat: 41.0525926
client.js?ea76789cca0ff64d5985320ec2127d5de1fb802f:25 Long: -73.5398427
client.js?ea76789cca0ff64d5985320ec2127d5de1fb802f:27 ---------------------
leaflet-src.js:3511 Uncaught TypeError: Cannot read property 'addLayer' of     undefinedL.Marker.L.Class.extend.addTo @ leaflet-src.js:3511(anonymous function)     @ client.js?ea76789cca0ff64d5985320ec2127d5de1fb802f:28

EDIT 2: I wanted to keep this simple but here is my js in its entirety:

var map;
var latit;
var longit;

// on startup run resizing event
Meteor.startup(function() {
$(window).resize(function() {
$('#map').css('height', window.innerHeight - 82 - 45);
});
$(window).resize(); // trigger resize event 
});

// create marker collection
var Markers = new Meteor.Collection('markers');

Meteor.subscribe('markers');

 Template.map.rendered = function() {
 L.Icon.Default.imagePath = 'packages/bevanhunt_leaflet/images';

 if (navigator.geolocation) {
  navigator.geolocation.getCurrentPosition(function(position) {
    console.log('--- Your Position: ---');
    console.log('Lat: ' + position.coords.latitude);
    latit = position.coords.latitude;
    console.log('Long: ' + position.coords.longitude);
    longit = position.coords.longitude;
    console.log('---------------------');
    var abc = L.marker([position.coords.latitude, position.coords.longitude]).addTo(map);
} 
)}

map = L.map('map', {
  doubleClickZoom: false
}).setView([latit, longit], 13); //Error is somewhere before here!!

L.tileLayer.provider('Thunderforest.Outdoors').addTo(map);


map.on('dblclick', function(event) {
 Markers.insert({latlng: event.latlng});
});

//add markers
var query = Markers.find();
query.observe({
added: function (document) {
  var marker = L.marker(document.latlng).addTo(map)
    .on('click', function(event) {
      map.removeLayer(marker);
      Markers.remove({_id: document._id});
    });
},
//remove markers
removed: function (oldDocument) {
  layers = map._layers;
  var key, val;
  for (key in layers) {
    val = layers[key];
    if (val._latlng) {
      if (val._latlng.lat === oldDocument.latlng.lat && val._latlng.lng === oldDocument.latlng.lng) {
        map.removeLayer(val);
      }
    }
  }
}
});
};
like image 829
Steve C Avatar asked Jul 13 '15 17:07

Steve C


Video Answer


2 Answers

Thanks, @sosdoc , initializing those variables does help and will help me in the long term of my project. but for simply rendering the map at my current location i found an even easier answer! leaflet has a locate method built into it. instead of passing the 'uninitialized' latit and longit vars, i did this:

map = L.map('map', {doubleClickZoom: false}).locate({setView: true, maxZoom: 16});

which sets the map to your location. maxzoom is just a variable for the amount of times you can zoom and can be changed.

like image 127
Steve C Avatar answered Oct 01 '22 14:10

Steve C


From the full code you can see that the error is here

map = L.map('map', {
  doubleClickZoom: false
}).setView([latit, longit], 13); 

because latit and longit aren't set (in JS, they are undefined until you give them any value).

You might be getting confused because this code gets executed before any of the callbacks you defined: Template.map.rendered is executed after this script terminates.

A solution to this would be setting an initial value for those parameters

var latit = 0;
var longit = 0;

Your map will be initially centered west of Africa.

Then, when map.rendered is executed you'll need to recenter the map to the updated latit and longit variables (updating them won't update the map).

if (navigator.geolocation) {
  navigator.geolocation.getCurrentPosition(function(position) {
    latit = position.coords.latitude;
    longit = position.coords.longitude;
    // this is just a marker placed in that position
    var abc = L.marker([position.coords.latitude, position.coords.longitude]).addTo(map);
    // move the map to have the location in its center
    map.panTo(new L.LatLng(latit, longit));
} 

If you want to, you can also pass the marker's position to the panTo() function:

map.panTo(abc.getLatLng());

Finally, remember that whenever you're passing a function() to some other function, that will be executed later on in response to some event, this is done extensively in JavaScript.

like image 38
Sosdoc Avatar answered Oct 01 '22 14:10

Sosdoc