使用Google Maps API v3循环标记问题

我不确定为什么这不起作用。 我没有任何错误,但发生的是,无论我点击什么标记,它总是点击最后一个标记。 我不知道为什么,因为the_marker设置方式相同。 我怎样才能解决这个问题?:

(更新了新的jQuery + XML)

$(function(){ var latlng = new google.maps.LatLng(45.522015,-122.683811); var settings = { zoom: 15, center: latlng, disableDefaultUI:true, mapTypeId: google.maps.MapTypeId.SATELLITE }; var map = new google.maps.Map(document.getElementById("map_canvas"), settings); $.get('mapdata.xml',{},function(xml){ $('location',xml).each(function(i){ the_marker = new google.maps.Marker({ title:$(this).find('name').text(), map:map, clickable:true, position:new google.maps.LatLng( parseFloat($(this).find('lat').text()), parseFloat($(this).find('lng').text()) ) }); infowindow = new google.maps.InfoWindow({ content: $(this).find('description').text() }); new google.maps.event.addListener(the_marker, 'click', function() { infowindow.open(map,the_marker); }); }); }); }); 

您在以下循环中遇到了一个非常常见的闭包问题 :

 for(x in locations){ console.log(x); infowindow[x] = new google.maps.InfoWindow({content: x}); marker[x] = new google.maps.Marker({title:locations[x][0],map:map,position:locations[x][2]}); google.maps.event.addListener(marker[x], 'click', function() {infowindow[x].open(map,marker[x]);}); } 

封闭在闭包中的变量共享相同的单个环境,因此在执行click回调时,循环已经运行, x变量将指向最后一个条目。

您可以使用函数工厂解决更多闭包问题:

 function makeInfoWindowEvent(map, infowindow, marker) { return function() { infowindow.open(map, marker); }; } for(x in locations){ infowindow[x] = new google.maps.InfoWindow({content: x}); marker[x] = new google.maps.Marker({title: locations[x][0], map: map, position: locations[x][3]}); google.maps.event.addListener(marker[x], 'click', makeInfoWindowEvent(map, infowindow[x], marker[x]); } 

如果您不熟悉闭包的工作方式,这可能是一个非常棘手的主题。 您可以查看以下Mozilla文章以获得简要介绍:

  • 使用闭包

更新:

除了更新的问题,您还应该考虑以下事项:

  • 首先,请记住JavaScript没有块范围。 只有函数有范围。

  • 当您分配先前未使用var关键字声明的变量时,它将被声明为全局变量。 这通常被认为是JavaScript的一个丑陋的特征(或缺陷),因为它可以默默地隐藏许多错误。 因此应该避免这种情况。 你有两个这些隐含的全局变量的实例: the_markerthe_marker ,事实上,这就是你的程序失败的原因。

  • JavaScript有闭包。 这意味着内部函数可以访问外部函数的变量和参数。 这就是为什么您可以从addListener方法的回调函数访问the_markerthe_markermap 。 但是,因为您的the_markerthe_marker被视为全局变量,所以闭包不起作用。

您需要做的就是在声明它们时使用var关键字,如下例所示:

 $(function() { var latlng = new google.maps.LatLng(45.522015,-122.683811); var settings = { zoom: 15, center: latlng, disableDefaultUI: true, mapTypeId: google.maps.MapTypeId.SATELLITE }; var map = new google.maps.Map(document.getElementById("map_canvas"), settings); $.get('mapdata.xml', {}, function(xml) { $('location', xml).each(function(i) { var the_marker = new google.maps.Marker({ title: $(this).find('name').text(), map: map, clickable: true, position: new google.maps.LatLng( parseFloat($(this).find('lat').text()), parseFloat($(this).find('lng').text()) ) }); var infowindow = new google.maps.InfoWindow({ content: $(this).find('description').text(); }); new google.maps.event.addListener(the_marker, 'click', function() { infowindow.open(map, the_marker); }); }); }); }); 

这是我的方法。

 for(x in locations){ var name = locations[x][0]; var latlng = locations[x][3]; addMarker(map, name, latlng); } function addMarker(map, name, latlng){ var infoWin = new google.maps.InfoWindow({content: name}); var marker = new google.maps.Marker({ map: map, position: latlng, title: name }); google.maps.event.addListener(marker, 'click', function(){ infoWin.open(map, marker); }); }