【问题标题】:Looping through Markers with Google Maps API v3 Problem使用 Google Maps API v3 循环标记问题
【发布时间】:2013-10-11 14:54:07
【问题描述】:

我不确定为什么这不起作用。我没有任何错误,但发生的情况是,无论我点击什么标记,它总是点击最后一个标记。我不确定为什么,因为 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 Stunstarred, Portland, OR 97205?
  • @BalusC:创新住房:maps.google.com/… :)
  • 哈哈,老实说,我只是输入了坐标来欣赏波特兰市的美景 :)

标签: javascript jquery xml google-maps loops


【解决方案1】:

您在以下循环中有a very common closure problem

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:更新了我的答案。您应该简单地使用 var 关键字声明您的 the_markerinfowindow 变量。
  • 看起来这段代码不会在打开第二个信息窗口时关闭前一个信息窗口,这是真的吗@DanielVassallo
【解决方案2】:

这是我的方法。

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

【讨论】:

    猜你喜欢
    • 2011-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 2012-05-11
    相关资源
    最近更新 更多