javascript 设置 Leaflet.js 地图以显示当前位置
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31389586/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
set leaflet.js map to display current location
提问by Steve C
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:
我正在使用用于meteor 的leaflet.js 包,但无法将地图默认为我在初始渲染时的当前位置。setView 方法适用于硬数字,但它不喜欢我的变量。我对 js 很陌生,所以也许错误很明显。这是我所拥有的:
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!
当我 console.log(latit) 或 console.log(longit) 它返回数字,以及它后面的“未定义”。在此先感谢任何可以帮助解决此问题的人!
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:
编辑 2:我想保持这个简单,但这里是我的 js 的全部内容:
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);
}
}
}
}
});
};
回答by Steve C
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:
谢谢,@sosdoc,初始化这些变量确实有帮助,并且对我的项目有长期帮助。但是为了简单地在我当前的位置渲染地图,我找到了一个更简单的答案!传单有一个内置的定位方法。我没有传递“未初始化”的纬度和经度变量,而是这样做了:
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.
它将地图设置为您的位置。maxzoom 只是您可以缩放和更改的次数的变量。
回答by Sosdoc
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).
因为latit
和longit
没有设置(在 JS 中,它们是未定义的,直到你给它们任何值)。
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.
您可能会感到困惑,因为此代码在您定义的任何回调之前Template.map.rendered
执行:在此脚本终止后执行。
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).
然后,在map.rendered
执行时,您需要将地图重新定位到更新的纬度和经度变量(更新它们不会更新地图)。
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:
如果需要,您还可以将标记的位置传递给panTo()
函数:
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.
最后,请记住,每当您将 a 传递function()
给某个其他函数时,该函数将在稍后执行以响应某个事件,这在 JavaScript 中广泛完成。
回答by witycode
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 © <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
//可以参考进一步的传单教程