Цикличное выполнение через Маркеры с проблемой Google Maps API v3

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

1 ответ

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

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

Переменные, заключенные в закрытие, используют одну и ту же единую среду, поэтому к моменту времени обратные вызовы щелчка будут выполняется, цикл завершился, и переменная 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_marker и infowindow , и, собственно, именно поэтому ваша программа дает сбой.

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

Все, что вам нужно сделать, это использовать ключевое слово 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);
         });
      });
   });
});
21
ответ дан 30 November 2019 в 04:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: