当点击标记时,Google地图v3会打开最后一个infoWindow [英] Google Maps v3 opens the last infoWindow when a marker is clicked
问题描述
我有一个共享的 infoWindow
所有我的标记。如果我使用jquery的 $()。每个(function(){})
,但是如果我把它改为JavaScrips的原生for或while循环,预期。
每当我点击某个标记时,它会打开最后一个填充标记的 infoWindow
,而不是点击的标记 infoWindow
。
这样工作:
code> $(stores).each(function(){
var storeId = $(this).attr('storeId');
var address = .attr('rawAddress');
var city = $(this).attr('city');
var state = $(this).attr('state');
var zip = $(this).attr('zip');
var lat = $(this).attr('lat');
var lng = $(this).attr ');
var distance = $(this).attr('distance');
//创建标记
var point = new google.maps.LatLng(lat, lng);
var marker = new google.maps.Marker({position:point
,map:InStorePickup.map
,title:city +'#'+ storeId
});
//创建infowindow内容
var infoWindowContent ='< div style =font-size:8pt;>'
+'< ; strong>'+ city +'#'+ storeId +'< / strong> ('+ parseFloat(distance).toFixed(2)+'mi)< br />'
+ address +'>'+ city +','+ state + zip
+'< / div>';
google.maps.event.addListener(marker,'click',function(){
InStorePickup.openInfoWindow(marker,infoWindowContent);
});
bounds.extend(point);
});
但这不起作用:
for(var i = 0; i <3; i ++){
var store = stores [i];
var storeId = $(store).attr('storeId');
var address = $(store).attr('rawAddress');
var city = $(store).attr('city');
var state = $(store).attr('state');
var zip = $(store).attr('zip');
var lat = $(store).attr('lat');
var lng = $(store).attr('lng');
var距离= $(this).attr('distance');
//创建标记
var point = new google.maps.LatLng(lat,lng);
var marker = new google.maps.Marker({position:point
,map:InStorePickup.map
,title:city +'#'+ storeId
});
//创建infowindow内容
var infoWindowContent ='< div style =font-size:8pt;>'
+'< strong> +'#'+ storeId +'< / strong> ('+ parseFloat(distance).toFixed(2)+'mi)< br />'
+ address +'>'+ city +','+ state + zip
+'< / div>';
google.maps.event.addListener(marker,'click',function(){
InStorePickup.openInfoWindow(marker,infoWindowContent);
});
bounds.extend(point);任何想法?
h2_lin>解决方案您将拥有在中
循环中的一个非常常见的闭包问题。顺便说一下,我昨天就这个话题回答了类似的问题
封闭在一个闭包中的变量共享同一个单一环境,所以到点击
callback被调用,循环将运行它的路线,并且 infoWindowContent
变量将指向它分配给的最后一个值。
一个解决方法是使用更多的闭包,使用函数工厂:
makeInfoWindowListener(pMarker,pContent){
return function(){
InStorePickup.openInfoWindow(pMarker,pContent);
};
}
// ...
for(var i = 0; i <3; i ++){
// ...
var infoWindowContent ='< div style =font-size:8pt;>'+ city +'...< / div>';
google.maps.event.addListener(
marker,
'click',
makeInfoWindowListener(marker,infoWindowContent)
);
}
这可能是一个相当棘手的话题,如果你不熟悉如何封闭工作。您可能有兴趣查看以下文章以获取简要说明:
UPDATE:
jQuery示例工作原因是因为您传递的函数到 each()
方法将每个迭代包含在其自身的作用域中。你可以在纯JavaScript示例中做同样的事情:
for(var i = 0; i <3; i ++ ){
//每个迭代现在都有自己的范围
(function(){
var infoWindowContent ='< div style = :8pt;>'+ city +'...< / div>';
google.maps.event.addListener(marker,'click',function(){
InStorePickup.openInfoWindow(marker,infoWindowContent);
});
})();
}
:
请注意,第一个示例也可以使用匿名函数重写如下:
for(var i = 0; i <3; i ++){
// ...
var infoWindowContent = '< div style =font-size:8pt;>'+ city +'...< / div>';
google.maps.event.addListener(marker,'click',(function(pMarker,pContent){
return function(){
InStorePickup.openInfoWindow(pMarker,pContent );
};
})(marker,infoWindowContent));
}
I have a shared infoWindow
for all my markers. It works good if I use jquery's $().each(function(){})
, but if I change it to JavaScrips's native for or while loop, it's not working as expected.
Whenever I click a marker, it will open the last populated marker's infoWindow
, instead of the clicked marker's infoWindow
.
This works:
$(stores).each(function() {
var storeId = $(this).attr('storeId');
var address = $(this).attr('rawAddress');
var city = $(this).attr('city');
var state = $(this).attr('state');
var zip = $(this).attr('zip');
var lat = $(this).attr('lat');
var lng = $(this).attr('lng');
var distance = $(this).attr('distance');
//create marker
var point = new google.maps.LatLng(lat, lng);
var marker = new google.maps.Marker({ position: point
, map: InStorePickup.map
, title: city + ' #' + storeId
});
//create infowindow content
var infoWindowContent = '<div style="font-size: 8pt;">'
+ '<strong>' + city + ' #' + storeId + '</strong> (' + parseFloat(distance).toFixed(2) + 'mi)<br />'
+ address + '<br />' + city + ', ' + state + ' ' + zip
+ '</div>';
google.maps.event.addListener(marker, 'click', function() {
InStorePickup.openInfoWindow(marker, infoWindowContent);
});
bounds.extend(point);
});
But this does not work:
for (var i = 0; i < 3; i++) {
var store = stores[i];
var storeId = $(store).attr('storeId');
var address = $(store).attr('rawAddress');
var city = $(store).attr('city');
var state = $(store).attr('state');
var zip = $(store).attr('zip');
var lat = $(store).attr('lat');
var lng = $(store).attr('lng');
var distance = $(this).attr('distance');
//create marker
var point = new google.maps.LatLng(lat, lng);
var marker = new google.maps.Marker({ position: point
, map: InStorePickup.map
, title: city + ' #' + storeId
});
//create infowindow content
var infoWindowContent = '<div style="font-size: 8pt;">'
+ '<strong>' + city + ' #' + storeId + '</strong> (' + parseFloat(distance).toFixed(2) + 'mi)<br />'
+ address + '<br />' + city + ', ' + state + ' ' + zip
+ '</div>';
google.maps.event.addListener(marker, 'click', function() {
InStorePickup.openInfoWindow(marker, infoWindowContent);
});
bounds.extend(point);
}
Any thoughts?
解决方案 You would be having a very common closure problem in the for
loop. Incidentally I have answered a similar question on this topic just yesterday, which you may want to check out.
Variables enclosed in a closure share the same single environment, so by the time the click
callback is called, the loop will have run its course and the infoWindowContent
variable will be left pointing to the last value it was assigned to.
One way to solve this is with more closures, using a function factory:
function makeInfoWindowListener (pMarker, pContent) {
return function() {
InStorePickup.openInfoWindow(pMarker, pContent);
};
}
// ...
for (var i = 0; i < 3; i++) {
// ...
var infoWindowContent = '<div style="font-size: 8pt;">' + city + '...</div>';
google.maps.event.addListener(
marker,
'click',
makeInfoWindowListener(marker, infoWindowContent)
);
}
This can be quite a tricky topic, if you are not familiar with how closures work. You may be interested in checking out the following article for a brief introduction:
UPDATE:
The reason why the jQuery example works, is because the function you pass to the each()
method encloses each iteration in its own scope. You could practically do the same thing in your plain JavaScript example:
for (var i = 0; i < 3; i++) {
// each iteration will now have its own scope
(function () {
var infoWindowContent = '<div style="font-size: 8pt;">' + city + '...</div>';
google.maps.event.addListener(marker, 'click', function() {
InStorePickup.openInfoWindow(marker, infoWindowContent);
});
})();
}
2nd UPDATE:
Note that the first example can also be rewritten as follows, using an anonymous function:
for (var i = 0; i < 3; i++) {
// ...
var infoWindowContent = '<div style="font-size: 8pt;">' + city + '...</div>';
google.maps.event.addListener(marker, 'click', (function (pMarker, pContent) {
return function() {
InStorePickup.openInfoWindow(pMarker, pContent);
};
})(marker, infoWindowContent));
}
这篇关于当点击标记时,Google地图v3会打开最后一个infoWindow的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!