API Карт Google v3 добавляет InfoWindow к каждому маркеру
ПРИМЕЧАНИЕ. Я использую v3 API Карт Google.
Я пытаюсь добавить информационное окно к каждому маркеру, который я помещаю на карту. В настоящее время я делаю это со следующим кодом:
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, но я не постингирую. Любые идеи?
Ответы
Ответ 1
У вас очень распространенная проблема закрытия в цикле 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 для краткого введения:
Также имейте в виду, что API v3 допускает множественные InfoWindow
на карте. Если вы намереваетесь иметь только один InfoWindow
, видимый в то время, вместо этого вы должны использовать единственный объект InfoWindow
, а затем открыть его и изменить его содержимое всякий раз, когда щелкнет маркер (Источник).
Ответ 2
Вы можете использовать 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.
});
Ответ 3
У 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, вы, вероятно, захотите использовать карту, в которой маркер принадлежит в любом случае.
Ответ 4
Использовать блокировки событий...
Вот как это сделать в v3: https://developers.google.com/maps/documentation/javascript/examples/event-closure
Ответ 5
Привет всем. Я не знаю, является ли это оптимальным решением, но я решил, что отправлю его здесь, чтобы надеяться помочь людям в будущем. Прокомментируйте, если вы видите что-то, что нужно изменить.
My for loops теперь:
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 в любое время. Надеюсь, это поможет кому-то.
Ответ 6
для 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);
});
}
Ответ 7
В моем случае (с использованием Javascript insidde Razor) Это отлично работало внутри цикла Foreach
google.maps.event.addListener(marker, 'click', function() {
marker.info.open(map, this);
});
Ответ 8
Попробуйте следующее:
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);
}
Ответ 9
У меня была очень похожая проблема, но в ActionScript 3:
Stack Over Flow: динамическое окно API-интерфейса API Карт Google Проблема с HTML-контентом
Я пытался извлечь уникальную информацию в htmlcontent всплывающих подсказок из базы данных и обнаружил, что получаю информацию о последнем маркере, который я добавил в каждом маркере.
Предполагая, что это не специфическая проблема с ActionScript, решение JochenJung не будет работать. Посмотрите на решение, которое я разместил в своей проблеме, и посмотрим, можете ли вы применить его здесь. Это похоже на серьезную проблему с API карт.
Ответ 10
Единственный способ, с помощью которого я мог бы заставить это работать, - создать массив в 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);
});
}
Ответ 11
У меня была аналогичная проблема.
Если все, что вам нужно, - это некоторая информация, отображаемая при наведении указателя мыши на маркер, вместо того, чтобы нажимать на нее, я обнаружил, что хорошей альтернативой использованию информационного окна было задание заголовка на маркере. Таким образом, всякий раз, когда вы наводите указатель мыши на маркер, заголовок отображается как тег ALT. 'marker.setTitle(' Маркер '+ id);'
Это устраняет необходимость создания слушателя для маркера тоже