注意:我正在使用Google Maps API的v3
我正在尝试为我放在地图上的每个标记添加一个信息窗口。目前我正在使用以下代码执行此操作:
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部分,但不是postitive。有什么想法吗?
答案 0 :(得分:79)
for in
循环中有a very common closure problem:
封闭在闭包中的变量共享相同的单一环境,因此当调用来自click
的{{1}}回调时,循环将运行其路径和addListener
变量将指向最后一个对象,这恰好是最后创建的info
。
在这种情况下,解决此问题的一种简单方法是使用InfoWindow
扩充Marker
对象:
InfoWindow
如果你不熟悉闭包的工作方式,这可能是一个非常棘手的话题。您可以查看以下Mozilla文章以获得简要介绍:
另请注意,v3 API允许在地图上显示多个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);
});
。如果您打算当时只有一个InfoWindow
可见,则应该使用单个InfoWindow
对象,然后在单击标记时打开它并更改其内容(Source)
答案 1 :(得分:35)
您可以在事件中使用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.
});
答案 2 :(得分: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;
}
我还使用了标记中的地图,这样你就不需要传递谷歌地图对象,你可能想要使用标记所属的地图。
答案 3 :(得分:1)
我的for循环现在是:
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。希望这有助于某人。
答案 4 :(得分:1)
对于地球插件API,在循环外创建气球并将计数器传递给函数以获取每个地标的唯一内容!
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);
});
}
答案 5 :(得分:1)
在我的情况下(使用Javascript insidde Razor)这在Foreach循环中完美地运行
google.maps.event.addListener(marker, 'click', function() {
marker.info.open(map, this);
});
答案 6 :(得分: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);
}
答案 7 :(得分: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);
});
}
答案 8 :(得分:0)
我有类似的问题。 如果你想要的只是当你将鼠标悬停在标记上而不是点击它时显示某些信息,那么我发现使用信息窗口的一个很好的替代方法是在标记上设置标题。这样,只要将鼠标悬停在标记上,标题就会显示为ALT标记。 'marker.setTitle('Marker'+ id);' 它也不需要为标记创建一个监听器