Javascript Google Maps API v3为每个标记添加一个信息窗口

Javascript Google Maps API v3为每个标记添加一个信息窗口,javascript,google-maps,google-maps-api-3,Javascript,Google Maps,Google Maps Api 3,注意:我使用的是谷歌地图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.qs

注意:我使用的是谷歌地图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);
}
for(赛车道[racer_id].data.points中的变量i){
数值=赛道[racer_id]。数据。点[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});
赛道[racer_id]。标记[i]=标记;
var info=new google.maps.InfoWindow({
内容:“速度:”+values.inst+“节”
});
赛道[racer_id].info[i]=info;
google.maps.event.addListener(标记'click',函数(){
信息打开(地图、标记);
});
}
轨迹坐标推(点);
bd.extend(点);
}
问题是,当我单击一个标记时,它只显示最后添加的标记的信息窗口。另外,为了清楚起见,信息窗口显示在最后一个标记旁边,而不是单击的标记旁边。我想象我的问题在addListener部分,但我不是积极的。有什么想法吗?

试试这个:

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);
}
for(赛车道[racer_id].data.points中的变量i){
数值=赛道[racer_id]。数据。点[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});
赛道[racer_id]。标记[i]=标记;
var info=new google.maps.InfoWindow({
内容:“速度:”+values.inst+“节”
});
赛道[racer_id].info[i]=info;
google.maps.event.addListener(跟踪[racer_id].markers[i],'click',函数(){
赛道[racer_id]。信息[i]。打开(地图,赛道[racer_id]。标记[i]);
});
}
轨迹坐标推(点);
bd.extend(点);
}
您在
for in
循环中有:

包含在闭包中的变量共享同一个环境,因此当调用来自
addListener
单击
回调时,循环将已运行,并且
info
变量将向左指向最后一个对象,该对象恰好是创建的最后一个
InfoWindow

在这种情况下,解决此问题的一个简单方法是使用
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);
});
var marker=new google.maps.marker({map:map,position:point,clickable:true});
marker.info=new google.maps.InfoWindow({
内容:“速度:”+values.inst+“节”
});
google.maps.event.addListener(标记'click',函数(){
标记信息打开(地图,标记);
});
如果您不熟悉闭包的工作方式,这可能是一个相当棘手的话题。您可以查看以下Mozilla文章以获得简要介绍:


还要记住,v3api允许在地图上显示多个
InfoWindow
s。如果您希望在此时只显示一个
InfoWindow
,则应使用单个
InfoWindow
对象,然后在单击标记时打开它并更改其内容()。

大家好。我不知道这是否是最佳解决方案,但我想我会把它贴在这里,希望将来能帮助人们。如果您看到任何需要更改的内容,请发表评论

我的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);
}

您可以使用info\u window.close()随时关闭info\u窗口。希望这对其他人有所帮助。

添加标记仍然存在关闭问题,因为它在google.maps.event.addListener范围之外使用了marker变量

更好的实施方式是:

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 map对象,您可能希望使用标记所属的地图。

对于Earth插件API,在循环外创建气球,并将计数器传递给函数,以获取每个placemark的唯一内容

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

在以下情况下,您可以使用此:

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

我最终能够实现这一点的唯一方法是用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);
    });
}
我也有类似的问题。 如果您只想在将鼠标悬停在标记上时显示一些信息,而不是单击它,那么我发现使用信息窗口的一个好方法是在标记上设置标题。这样,每当您将鼠标悬停在标记上时,标题就会显示为ALT标记。 'marker.setTitle('marker'+id);' 在我的例子中(使用Javascript inside Razor),它消除了为标记创建监听器的需要,这在Foreach循环中非常有效

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

哈哈,我已经试过了。只是再试了一次,不幸的是它仍然不起作用。这里的问题是
i
变量,它仍然包含在闭包中。调用
click
回调时,
i
变量将指向循环的最后一项,因此
info[i]。open
仍将打开最后一个
InfoWindow
。您能解释一下我需要在哪里插入此代码段吗?我有点困惑。使用marker.info.open(map,this)在一个稍微不同的用例中为我工作。这应该是正确的答案。@DanielVassallo的答案和他提到的问题一样。效果很好,但我必须做
这个.info.open(marker\u map,这个)使用
此.info.open(标记地图,此)
;到
google.maps.event.addListener(marker, 'click', function() {
    marker.info.open(map, this);
});