【问题标题】:Adding multiple markers with infowindows (Google Maps API)使用信息窗口添加多个标记(Google Maps API)
【发布时间】:2011-10-26 01:16:42
【问题描述】:

我目前正在使用以下代码,使用他们的 API 在 Google 地图上放置多个标记。

我遇到的问题是多个信息窗口不起作用(仅显示最后一个)。

在 SO 上有很多像我这样的问题。实际上提出了一大堆问题:-)

只是一个例子:Trying to bind multiple InfoWindows to multiple Markers on a Google Map and failing

我的问题的解决方案很简单:只需将点击侦听器附在一个(匿名)函数中即可。

但是我不明白为什么我的解决方案不起作用(将标记和信息窗口保存在数组中,而不仅仅是一个变量)。

    var markers = [];
    var infowindows = [];

    // add shops or malls
    for (var key in data.markers) {
      if (data.markers.hasOwnProperty(key)) {
        infowindows[key] = new google.maps.InfoWindow({
            content: data.markers[key].infowindow
        });

        markers[key] = new google.maps.Marker({
                position: new google.maps.LatLng(data.markers[key].location.lat, data.markers[key].location.lng),
                map: map,
                flat: true,
                title: data.markers[key].name,
                draggable: false
        });
        var iconFile = 'http://maps.google.com/mapfiles/ms/icons/'+marker_color+'-dot.png';
        markers[key].setIcon(iconFile);

        google.maps.event.addListener(markers[key], 'click', function() {
          infowindows[key].open(map, markers[key]);
        });
      }
    }

所以......我不知道如何获得解决方案如何让它与一些功能一起工作以封闭监听器(虽然它应该工作,还没有测试过但会),但我想知道如果我将标记和信息窗口添加到数组中,它不会起作用的原因。

【问题讨论】:

    标签: google-maps google-maps-api-3


    【解决方案1】:

    Javascript 有一种称为“闭包”的语言结构。闭包是捕获对外部变量的引用的函数(例如您在上面声明的用于处理点击侦听器的 function() {})。

    有很多资源比我能更好地解释它们,我建议你参考,但这是我最好的尝试:

    在此块中:

        google.maps.event.addListener(markers[key], 'click', function() {
          infowindows[key].open(map, markers[key]);
        });
    

    因为“key”已经被定义为一个外部变量,该函数将捕获对该变量的引用。所以你期望的地方:

    infowindows["helloworld"]
    

    Javascript 会将其解释为:

    infowindows[reference to key]
    

    当您单击标记时,它会查找“对键的引用”以查看键的当前值。因为这可能在循环完成之前不会发生,所以 key 将等于 data.markers 对象中的最后一个键。对于您添加的每个点击侦听器,它将等于该值。

    正如您所指出的,解决方案是将其包装在一个匿名函数中,以让 Javascript 在添加点击侦听器时评估“键”的值。

      google.maps.event.addListener(markers[key], 'click', function(innerKey) {
          return function() {
              infowindows[innerKey].open(map, markers[innerKey]);
          }
        }(key));
    

    【讨论】:

      【解决方案2】:

      这对我来说很好用!只需向标记对象添加一个新属性,该属性包含信息窗口对象。

      var mytext = 'Infowindow contents in HTML'
      var myinfowindow = new google.maps.InfoWindow({
          content: mytext
      });
      
      var marker = new google.maps.Marker({
          position: mypos,
          map: mymap,
          icon: myicon,
          title: mytitle,
          infowindow: myinfowindow
      });
      
      google.maps.event.addListener(marker, 'click', function() {
              this.infowindow.open(map, this);
      
      });
      

      【讨论】:

      • 这根本不回答原来的问题!它仅显示了带有 ONE 信息窗口的 Google Maps API 参考中的示例。对不起,这个答案不应该在这里。
      【解决方案3】:

      有一种稍微简单的方法可以完成此操作。您可以将自定义属性添加到标记(信息窗口的索引)并在回调函数中引用它。下面的例子:

          markers = Array();
          infoWindows = Array();
      
          for(var i in earthquakes)
          {
              var location = new google.maps.LatLng(earthquakes[i].geolat, earthquakes[i].geolong);
              var marker = new google.maps.Marker({
                  position : location,
                  map : map,
                  animation : google.maps.Animation.DROP,
                  infoWindowIndex : i //<---Thats the extra attribute
              });
              var content = "<h3>" + earthquakes[i].title + "<h3>" +
                      "<a data-ajax='false' target='_blank' href='" + earthquakes[i].link + "'>Link to shakemap.</a>";
              var infoWindow = new google.maps.InfoWindow({
                  content : content
              });
      
              google.maps.event.addListener(marker, 'click', 
                  function(event)
                  {
                      map.panTo(event.latLng);
                      map.setZoom(5);
                      infoWindows[this.infoWindowIndex].open(map, this);
                  }
              );
      
              infoWindows.push(infoWindow);
              markers.push(marker);
          }
      

      【讨论】:

      • 我正在尝试这种方式,但我有一个 jshint 警告“不要在循环中创建函数”。如果我将侦听器置于循环之外,则会出现“标记超出范围”错误。我该如何避免呢?
      【解决方案4】:
          function addMarker(Latlng){ 
             marker = new google.maps.Marker({
                  position: Latlng,
                  icon:"myicon.jpg",
                  map: map,
                  animation: google.maps.Animation.DROP,
                  title:"My tooltip"
              });
      
              //add marker
              marker.setMap(map);
      
              contentString = "<h1>Hello World</h1>";
      
              marker.infowindow = new google.maps.InfoWindow({
                  content: contentString
              });
      
              //add click event
              google.maps.event.addListener(marker, 'click', function(){
                  this.infowindow.open(map,this);
              });
          }
      
          addMarker(some_lat_lang_value);
      

      【讨论】:

        【解决方案5】:

        我将使用闭包:

        (function(infowindow, marker){google.maps.event.addListener(marker, 'click', function() {
          infowindow.open(map, marker);
        });})(infowindow, marker)
        

        【讨论】:

          【解决方案6】:
          var infowindow = null;
          infowindow = new google.maps.InfoWindow({
            content: "loading..."
          });
          for (i = 0; i < data.dbreturn.length; i++) { 
            var latilongi = data.dbreturn[i].mapa.split(',');
            var mapinha =  {lat: parseFloat(latilongi['0']), lng:     parseFloat(latilongi['1'])};
            var marker = new google.maps.Marker({
            position: mapinha,
            html: '<div id="content"><h5 id="firstHeading"     class="firstHeading">'+data.dbreturn[i].nome+'</h5></div>'
          });
          
          google.maps.event.addListener(marker, "click", function () {
            infowindow.setContent(this.html);
            infowindow.open(map, this);
          });
          }
          

          【讨论】:

          • 欢迎来到 Stack Overflow!虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-02-02
          • 2018-04-02
          • 2014-02-18
          • 2015-11-21
          • 2013-08-14
          • 2013-05-25
          • 2011-06-22
          相关资源
          最近更新 更多