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

Osc*_*son 19 javascript xml jquery google-maps loops

我不确定为什么这不起作用.我没有任何错误,但发生的是,无论我点击什么标记,它总是点击最后一个标记.我不知道为什么,因为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);
            });
        });
    });
});
Run Code Online (Sandbox Code Playgroud)

Dan*_*llo 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]);});
}
Run Code Online (Sandbox Code Playgroud)

封闭在闭包中的变量共享相同的单个环境,因此在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]);
}
Run Code Online (Sandbox Code Playgroud)

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


更新:

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

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

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

  • JavaScript有闭包.这意味着内部函数可以访问外部函数的变量和参数.这就是为什么你将能够访问the_marker,infowindowmap从回调函数addListener方法.但是,因为您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);
         });
      });
   });
});
Run Code Online (Sandbox Code Playgroud)