最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Set leaflet.js map to display user's current location - Stack Overflow

programmeradmin0浏览0评论

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);
      }
    }
  }
}
});
};

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);
      }
    }
  }
}
});
};
Share Improve this question edited Jun 7, 2024 at 13:04 Kalnode 11.3k3 gold badges40 silver badges73 bronze badges asked Jul 13, 2015 at 17:19 Steve CSteve C 5571 gold badge3 silver badges15 bronze badges 7
  • Can you give the exact output of the console? – Vale Commented Jul 13, 2015 at 17:35
  • where do you declare latit and longit? (Do you say var latit somewhere?) – sfletche Commented Jul 13, 2015 at 17:48
  • @Stevec we're missing the big picture but it looks like your rendered callback doesn't have access to the map because latit and longit are undefined the first time around, do you ever initialize them? A console.log() right before the L.map call would help – Vale Commented Jul 13, 2015 at 17:48
  • @sfletche i do say var latit; and var longit; at the top of my js, before any functions – Steve C Commented Jul 13, 2015 at 17:51
  • @SteveC - I ask about declaration for the same reasons @Sosdoc is asking. It sounds like your setView call is being made outside the scope in which your latit and longit variables are declared. Is that possible? – sfletche Commented Jul 13, 2015 at 17:55
 |  Show 2 more comments

3 Answers 3

Reset to default 21

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.

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.

navigator.geolocation.getCurrentPosition(function(location) {
  var latlng = new L.LatLng(location.coords.latitude, location.coords.longitude);
   alert(latlng);
  var mymap = L.map('mapid').setView(latlng, 13)
  L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', {
    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="https://mapbox.com">Mapbox</a>',
    maxZoom: 18,
    id: 'mapbox.streets',
    accessToken: 'pk.eyJ1IjoiYmJyb29rMTU0IiwiYSI6ImNpcXN3dnJrdDAwMGNmd250bjhvZXpnbWsifQ.Nf9Zkfchos577IanoKMoYQ'
  }).addTo(mymap);

  var marker = L.marker(latlng).addTo(mymap);
});
#mapid { 
  height: 500px;
}
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="https://d3js.org/topojson.v0.min.js"></script>
	<link rel="stylesheet" href="https://npmcdn.com/[email protected]/dist/leaflet.css" />
	 <script src="https://npmcdn.com/[email protected]/dist/leaflet.js"></script>

<div id="mapid"></div>

//further leaflet tutorial may be referred

发布评论

评论列表(0)

  1. 暂无评论