使用Google Maps API v3遍历标记的问题

19
我不确定为什么这不起作用。我没有任何错误,但发生的情况是,无论我点击哪个标记,它总是点击最后一个标记。我不确定为什么,因为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);
            });
        });
    });
});

1201-1299 SW Washington St,Portland,OR 97205有什么? - BalusC
哈哈,说实话,我只是随便加了一些坐标,以便能够看到波特兰市的好景色 :) - Oscar Godson
2个回答

21

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

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_markerinfowindow,而实际上,这就是您的程序失败的原因。

  • JavaScript有闭包。这意味着内部函数可以访问外部函数的变量和参数。这就是为什么您可以从addListener方法的回调函数中访问the_markerinfowindowmap的原因。但是,由于您的the_markerinfowindow被视为全局变量,闭包无法正常工作。

您需要做的就是在声明它们时使用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);
         });
      });
   });
});

抱歉,您能否使用我的当前代码向我展示一下?我有点困惑。:\ 感谢您的所有帮助。我必须更新它以使用jQuery和XML文件。 - Oscar Godson
1
@Oscar:我更新了我的答案。你应该使用“var”关键字声明你的“the_marker”和“infowindow”变量。 - Daniel Vassallo
看起来这段代码在打开第二个信息窗口时没有关闭先前的信息窗口,是这样吗 @DanielVassallo - Mike

3

这是我的方法。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接