API карт Google v3 - добавление нескольких инфо-окон

У меня есть рабочий раздел javascript для Google Maps, у меня была проблема.

Теперь проблема была в том, что появился только один infowindow, последний. Я нашел решение в другом потоке стека, которое получилось. Но я не мог понять, почему. Я новичок в Javascript, поэтому я надеялся, что кто-то сможет объяснить мне, что изменилось и как.

Вот рабочий код:

function setMarkers(map, locations){
  for(var i = 0; i < locations.length; i++){
    var marker = locations[i];
    var latLng = new google.maps.LatLng(locations[i][1], locations[i][2]);
    var content = locations[i][0];
    var infowindow = new google.maps.InfoWindow();

    marker = new google.maps.Marker({
      position:latLng,
      map: map
    });

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

Вот исходный сломанный код (я вставляю только то, что изменилось):

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

Теперь, что я хотел бы знать, если вы будете такими добрыми, это:

  • какая функция возвращает return fn, а

  • что добавляет добавленный (content) в конце addListener (}(content));), поскольку, насколько я вижу, контент уже установлен в свойстве setContent.

Благодарственные!

Ответ 1

Не зацикливайте свой infowindow...
Вам нужен только один экземпляр объекта infowindow object.
Переместите его за пределы цикла, то же самое для ваших функций.
Внутри цикла назначьте его содержимое по отношению к нажатому marker

const locations = [
  {lat: 45.840196, lng: 15.964331, name: "Zagreb"},
  {lat: 43.514851, lng: 16.449083, name: "Split"},
  {lat: 42.645725, lng: 18.094058, name: "Dubrovnik"},
];

function initGoogleMap(){

  const infowindow = new google.maps.InfoWindow(); // Only one InfoWindow
  const map = new google.maps.Map(document.getElementById('map-canvas'), {
      zoom: 6,
      center: new google.maps.LatLng(45, 15)
  });
  
  function placeMarker( loc ) {
    const marker = new google.maps.Marker({
      position : new google.maps.LatLng( loc.lat, loc.lng ),
      map : map
    });
    google.maps.event.addListener(marker, 'click', function(){
        infowindow.close(); // Close previously opened infowindow
        infowindow.setContent('<div id="infowindow">${loc.name}</div>');
        infowindow.open(map, marker);
    });
  }
  
  // ITERATE ALL LOCATIONS. Pass every location to placeMarker
  locations.forEach( placeMarker );
  
}

google.maps.event.addDomListener(window, 'load', initGoogleMap);
html, body, #map-canvas { height: 100%; margin: 0px; }
#infowindow{ padding: 10px; }
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
<div id="map-canvas"></div>

Ответ 2

for(int i = 0; i < locations.length; i++){
    var latLng = new google.maps.LatLng(locations[i][1], locations[i][2]);
    var contentString = locations[i][0];

    marker = new google.maps.Marker({           
          position: latLng,
          map: map,
          contentString: contentString
    });

    var infowindow = new google.maps.InfoWindow({});

    marker.addListener('click', function() {
           infowindow.setContent(this.contentString);
           infowindow.open(map, this);
           map.setCenter(this.getPosition());
     });
}

Это отлично работает для меня

Ответ 3

По какой-то причине мне пришлось изменить объект-маркер и получить доступ к этим данным внутри функции lisener события.

Масштабы события щелчка по маркеру являются маркерным объектом.

var infowindow = new google.maps.InfoWindow();

for(int i = 0; i < locations.length; i++){
    var latLng = new google.maps.LatLng(locations[i][1], locations[i][2]);
    var contentString = locations[i][0];

    marker = new google.maps.Marker({           
          position: latLng,
          map: map,
          contentString: contentString
    });
    marker.data = locations[i]; // adds object to marker object


    marker.addListener('click', function() {
        // read custom data in this.data   
        infowindow.setContent("<div id='infowindow'>"+ this.data[0] +"</div>");

        infowindow.open(map, this);
        map.setCenter(this.getPosition());
     });
}

Ответ 4

var locations = [
  ["Split",     43.5148515, 16.4490835],
  ["Zagreb",    45.840196,  15.9643316],
  ["Dubrovnik", 42.6457256, 18.094058]
];

function initGoogleMap(){

  var infowindow = new google.maps.InfoWindow(); /* SINGLE */
  var map = new google.maps.Map(document.getElementById('map-canvas'), {
      zoom: 4,
      center: new google.maps.LatLng(45, 15)
  });
  
  function placeMarker( loc ) {
    var latLng = new google.maps.LatLng( loc[1], loc[2]);
    var marker = new google.maps.Marker({
      position : latLng,
      map      : map
    });
    google.maps.event.addListener(marker, 'click', function(){
        infowindow.close(); // Close previously opened infowindow
        infowindow.setContent( "<div id='infowindow'>"+ loc[0] +"</div>");
        infowindow.open(map, marker);
    });
  }
  
  // ITERATE ALL LOCATIONS
  // Don't create functions inside for loops
  // therefore refer to a previously created function
  // and pass your iterating location as argument value:
  for(var i=0; i<locations.length; i++) {
    placeMarker( locations[i] );
  } 
  
}
google.maps.event.addDomListener(window, 'load', initGoogleMap);
html, body, #map-canvas {
  height: 100%;
  margin: 0px;
  padding: 0px
}

#infowindow{
  padding: 10px;
}
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
<div id="map-canvas"></div>