Google Maps API v3将InfoWindow添加到每个标记
注意:我正在使用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部分,但不是联系。 有任何想法吗?
for in
循环中有一个非常常见的closures问题 :
包含在闭包中的variables共享相同的单一环境,所以当调用addListener
的click
callbackaddListener
,循环将运行, info
variables将指向最后一个对象,这恰好是最后一个对象InfoWindow
创build。
在这种情况下,解决这个问题的一个简单方法就是用InfoWindow
来扩充Marker
对象:
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 )。
你可以在事件中使用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. });
add_marker仍然有一个closures问题,因为它使用google.maps.event.addListener作用域之外的标记variables。
更好的实施将是:
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地图对象,也可以使用标记所属的地图。
使用事件closures…
这是如何在v3中完成的: https : //developers.google.com/maps/documentation/javascript/examples/event-closure
嘿大家。 我不知道这是否是最佳的解决scheme,但我想我会在这里发布,希望在未来帮助人们。 请留言,如果你看到任何应该改变。
现在我的循环是:
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()closuresinfo_window。 希望这有助于某人。
对于地球插件API,在您的循环外创build气球,并将您的计数器传递给函数,以获得每个地标的唯一内容!
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); }); }
在我的情况(使用Javascript insidde剃刀)这完美的内部Foreach循环
google.maps.event.addListener(marker, 'click', function() { marker.info.open(map, this); });
尝试这个:
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); }
我有一个非常类似的问题,但在ActionScript 3: 堆栈溢出:dynamicGoogle Maps API信息窗口HTML内容问题
我试图从数据库中提取独特的信息到工具提示的html内容中,发现我得到了每个标记中添加的最后一个标记的信息。
假设这不是一个动作特定的问题,那么JochenJung的解决scheme将无法正常工作。 看看我在问题中发布的解决scheme,看看你是否可以在这里应用它。 这似乎是Map API的严重问题。
我终于可以完成这个工作的唯一方法是通过在JavaScript中创build一个数组。 数组元素引用各种信息窗口(为地图上的每个标记创build一个信息窗口)。 每个数组元素都包含适当地图标记的唯一文本。 我为每个基于数组元素的信息窗口定义了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); }); }
我有一个类似的问题。 如果您只想将鼠标hover在某个标记上时显示某些信息,而不是点击它,则发现使用信息窗口的另一种方法是在标记上设置标题。 这样,只要将鼠标hover在标记上,标题就会显示为一个ALT标记。 'marker.setTitle('Marker'+ id);' 它也不需要为标记创build一个监听器