Цикл по маркерам с Google Maps API v3 Проблема - PullRequest
19 голосов
/ 19 апреля 2010

Я не уверен, почему это не работает. У меня нет никаких ошибок, но что бы ни случилось, независимо от того, на какой маркер я нажимаю, он всегда нажимает на последний маркер. Я не уверен почему, хотя, потому что 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);
            });
        });
    });
});

Ответы [ 2 ]

21 голосов
/ 19 апреля 2010

У вас очень распространенная проблема закрытия в следующем цикле:

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 для краткого введения:


UPDATE:

В дополнение к обновленному вопросу, вы должны рассмотреть следующее:

  • Прежде всего, имейте в виду, что JavaScript не имеет блочной области видимости. Только функции имеют область действия.

  • Когда вы назначаете переменную, которая ранее не была объявлена ​​с ключевым словом var, она будет объявлена ​​как глобальная переменная. Это часто считается уродливой особенностью (или недостатком) JavaScript, поскольку он может скрывать множество ошибок. Поэтому этого следует избегать. У вас есть два экземпляра этих подразумеваемых глобальных переменных: the_marker и infowindow, и именно поэтому ваша программа не работает.

  • В JavaScript есть замыкания. Это означает, что внутренние функции имеют доступ к переменным и параметрам внешней функции. Вот почему вы сможете получить доступ к the_marker, infowindow и map из функции обратного вызова метода addListener. Однако, поскольку ваши the_marker и infowindow обрабатываются как глобальные переменные, закрытие не работает.

Все, что вам нужно сделать, это использовать ключевое слово 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);
         });
      });
   });
});
3 голосов
/ 11 октября 2013

Вот мой подход.

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);
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...