2010-07-01 2 views
44

ПРИМЕЧАНИЕ: Я использую версию 3 API Карт GoogleGoogle Maps API v3 добавления InfoWindow к каждому маркеру

Я пытаюсь добавить информационное окно для каждого маркера я ставлю на карте. В настоящее время я делаю это с помощью следующего кода:

for (var i in tracks[racer_id].data.points) { 
    values = tracks[racer_id].data.points[i];     
    point = new google.maps.LatLng(values.lat, values.lng); 
    if (values.qst) { 
     var marker = new google.maps.Marker({map: map, position: point, clickable: true}); 
     tracks[racer_id].markers[i] = marker; 
     var info = new google.maps.InfoWindow({ 
      content: '<b>Speed:</b> ' + values.inst + ' knots' 
     }); 
     tracks[racer_id].info[i] = info; 
     google.maps.event.addListener(marker, 'click', function() { 
      info.open(map, marker); 
     }); 
    } 
    track_coordinates.push(point); 
    bd.extend(point); 
} 

Проблема заключается в том, когда я нажимаю на маркер это просто отображает информационное окно добавляется последний маркер. Также, чтобы быть понятным, информационное окно появляется рядом с последним маркером, а не маркером. Я бы предположил, что моя проблема заключается в части addListener, но я не постингирую. Есть идеи?

ответ

78

Вы имеете a very common closure problem в for in цикле:

переменные, заключенные в доле закрытия ту же единую среду, так что к тому времени, click обратного вызова из addListener называется, цикл будет идти своим курсом, а info переменная будет указана на последний объект, который создается последним InfoWindow.

В этом случае один простой способ решить эту проблему было бы дополнить свой Marker объект с InfoWindow:

var marker = new google.maps.Marker({map: map, position: point, clickable: true}); 

marker.info = new google.maps.InfoWindow({ 
    content: '<b>Speed:</b> ' + values.inst + ' knots' 
}); 

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

Это может быть весьма непростой вопрос, если вы не знакомы с тем, как работа укупорочных , Вы можете проверить следующую статью Mozilla для краткого введения:

Также имейте в виду, что v3 API позволяет нескольким InfoWindow с на карте. Если вы намереваетесь иметь только один InfoWindow, видимый в то время, вместо этого вы должны использовать один объект InfoWindow, а затем открыть его и изменить его содержимое всякий раз, когда нажимается маркер (Source).

+1

Можете ли вы объяснить, где мне нужно подключить этот фрагмент кода? Это делается вместо цикла loop или before for-loop. Я немного запутался. – uday

+1

Вам нужно вставить фрагмент кода _inside_ for for;;) – Tilt

0

Попробуйте это:

for (var i in tracks[racer_id].data.points) { 
    values = tracks[racer_id].data.points[i];     
    point = new google.maps.LatLng(values.lat, values.lng); 
    if (values.qst) { 
     var marker = new google.maps.Marker({map: map, position: point, clickable: true}); 
     tracks[racer_id].markers[i] = marker; 
     var info = new google.maps.InfoWindow({ 
      content: '<b>Speed:</b> ' + values.inst + ' knots' 
     }); 
     tracks[racer_id].info[i] = info; 
     google.maps.event.addListener(tracks[racer_id].markers[i], 'click', function() { 
      tracks[racer_id].info[i].open(map, tracks[racer_id].markers[i]); 
     }); 
    } 
    track_coordinates.push(point); 
    bd.extend(point); 
} 
+0

Ха-ха, я уже пробовал. Просто попробовал еще раз, и, к сожалению, он все еще не работает. – blcArmadillo

+0

Проблема здесь в переменной 'i', которая все еще заключена в закрытие. Когда вызывается обратный вызов 'click', переменная' i' будет указана на последний элемент цикла, и поэтому 'info [i] .open' все равно откроет последний' InfoWindow'. –

0

У меня была очень похожая проблема, но в ActionScript 3: Stack Over Flow: Dynamic Google Maps API Info Window HTML Content Issue

Я пытался вытащить уникальную информацию в htmlcontent из всплывающих подсказок из базы данных и обнаружили, что Я получал информацию о последнем маркере, который я добавил в каждом маркере.

Предполагая, что это не проблема конкретных действий, тогда решение JochenJung не будет работать. Посмотрите на решение, которое я разместил в своей проблеме, и посмотрим, можете ли вы применить его здесь. Это похоже на серьезную проблему с API карт.

1

Эй, все. Я не знаю, является ли это оптимальным решением, но я решил, что отправлю его здесь, чтобы надеяться помочь людям в будущем. Прошу прокомментировать, если вы видите что-то, что нужно изменить.

Мои для петель теперь:

for (var i in tracks[racer_id].data.points) { 
    values = tracks[racer_id].data.points[i];     
    point = new google.maps.LatLng(values.lat, values.lng); 
    if (values.qst) { 
     tracks[racer_id].markers[i] = add_marker(racer_id, point, '<b>Speed:</b> ' + values.inst + ' knots<br /><b>Invalid:</b> <input type="button" value="Yes" /> <input type="button" value="No" />'); 
    } 
    track_coordinates.push(point); 
    bd.extend(point); 
} 

И add_marker определяется как:

var info_window = new google.maps.InfoWindow({content: ''}); 

function add_marker(racer_id, point, note) { 
    var marker = new google.maps.Marker({map: map, position: point, clickable: true}); 
    marker.note = note; 
    google.maps.event.addListener(marker, 'click', function() { 
     info_window.content = marker.note; 
     info_window.open(map, marker); 
    }); 
    return marker; 
} 

Вы можете использовать info_window.close(), чтобы выключить info_window в любое время. Надеюсь, это поможет кому-то.

9

У объекта add_marker все еще есть проблема с закрытием, поскольку он использует переменную-маркер вне области google.maps.event.addListener.

Лучше реализация будет:

function add_marker(racer_id, point, note) { 
    var marker = new google.maps.Marker({map: map, position: point, clickable: true}); 
    marker.note = note; 
    google.maps.event.addListener(marker, 'click', function() { 
     info_window.content = this.note; 
     info_window.open(this.getMap(), this); 
    }); 
    return marker; 
} 

Я также использовал карту от маркеров, таким образом, вам не нужно, чтобы пройти карту объект Google, вы, вероятно, хотите использовать карту, где маркер В любом случае.

+0

Wow! Я застрял на этом больше двух часов! не знал, что маркер вне рамок будет использоваться! Благодаря тонну! –

1

для API плагинов Earth, создайте воздушный шар вне вашей петли и передайте счетчик функции, чтобы получить уникальное содержимое для каждой метки!

function createBalloon(placemark, i, event) { 
      var p = placemark; 
      var j = i; 
      google.earth.addEventListener(p, 'click', function (event) { 
        // prevent the default balloon from popping up 
        event.preventDefault(); 
        var balloon = ge.createHtmlStringBalloon(''); 
        balloon.setFeature(event.getTarget()); 

        balloon.setContentString('iframePath#' + j); 

        ge.setBalloon(balloon); 
      }); 
     } 
33

Вы можете использовать this в случае:

google.maps.event.addListener(marker, 'click', function() { 
    // this = marker 
    var marker_map = this.getMap(); 
    this.info.open(marker_map); 
    // this.info.open(marker_map, this); 
    // Note: If you call open() without passing a marker, the InfoWindow will use the position specified upon construction through the InfoWindowOptions object literal. 
}); 
+10

Это должен быть правильный ответ. Ответ @DanielVassallo страдает той же проблемой, с которой он связан. –

+0

Это тоже работало для меня. «Это» был ключом. –

+3

Отлично работает, но мне нужно было сделать this.info.open (marker_map, это); ' – askilondz

0

Единственный способ, которым я мог бы, наконец, получить эту работу было путем создания массива в JavaScript. Элементы массива ссылаются на различные инфо-окна (для каждого маркера на карте создается одно информационное окно). Каждый элемент массива содержит уникальный текст для соответствующего маркера карты. Я определил событие JavaScript для каждого информационного окна на основе элемента массива. И когда событие срабатывает, я использую ключевое слово this, чтобы ссылаться на элемент массива, чтобы ссылаться на соответствующее значение для отображения.

var map = new google.maps.Map(document.getElementById('map-div'), mapOptions); 
zipcircle = []; 
for (var zip in zipmap) { 
    var circleoptions = { 
     strokeOpacity: 0.8, 
     strokeWeight: 1, 
     fillOpacity: 0.35, 
     map: map, 
     center: zipmap[zip].center, 
     radius: 100 
    }; 
    zipcircle[zipmap[zip].zipkey] = new google.maps.Circle(circleoptions); 
    zipcircle[zipmap[zip].zipkey].infowindowtext = zipmap[zip].popuptext; 
    zipcircle[zipmap[zip].zipkey].infowindow = new google.maps.InfoWindow(); 
    google.maps.event.addListener(zipcircle[zipmap[zip].zipkey], 'click', function() { 
     this.infowindow.setContent(this.infowindowtext); 
     this.infowindow.open(map, this); 
    }); 
} 
4

Использование событий укупорочные ...

Это, как сделать это в v3: https://developers.google.com/maps/documentation/javascript/examples/event-closure

+1

Лучше включить пример вместо пересылки на ссылку. Если эта ссылка исчезнет, ​​ваш пример по-прежнему поможет, и вы ответите на очень старый вопрос (4 года). –

+1

Метод, показанный в этом примере, работал для меня. Создайте «информацию» в своем цикле, а затем создайте отдельную функцию, которая берет «маркер» и «информацию» для создания InfoWindow и слушателя для события. @ Ответ на ostapische создал правильные окна событий, но все они были в местах, которые не были связаны с определенным маркером. –

+0

Это хороший ресурс. ES2015 позволяет контролировать область блока, вероятно, позаботится об этом сейчас. – sheriffderek

0

У меня была аналогичная проблема. Если вы хотите, чтобы какая-то информация отображалась, когда вы наводили указатель мыши на маркер, вместо того, чтобы нажимать на нее, я обнаружил, что хорошей альтернативой использованию информационного окна было установить заголовок на маркере. Таким образом, всякий раз, когда вы наводите указатель мыши на маркер, заголовок отображается как тег ALT. 'marker.setTitle (' Маркер '+ id);' Это устраняет необходимость в создании слушателя для маркера слишком

1

В моем случае (с помощью Javascript insidde Razor) Это работало отлично внутри цикла Foreach

google.maps.event.addListener(marker, 'click', function() { 
    marker.info.open(map, this); 
}); 
Смежные вопросы