javascript 使用 api v3 将信息窗口添加到谷歌地图上的循环标记数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11507187/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 13:27:36  来源:igfitidea点击:

Add infowindow to looped array of markers on google map using api v3

javascriptgoogle-mapsgoogle-maps-api-3

提问by Steve Smith

I have an array that is being looped through in js to put custom markers on a google map. I need to add a hidden info window for each marker so that when it is clicked the relevant infowindow is displayed. Currently I am doing the following:

我有一个数组,它正在 js 中循环以将自定义标记放在谷歌地图上。我需要为每个标记添加一个隐藏的信息窗口,以便在单击时显示相关的信息窗口。目前我正在做以下事情:

for(var i=0; i<google_map_item.length; i++)
    {
        latlon = new google.maps.LatLng(google_map_item[i].lat, google_map_item[i].lon)
        bounds.extend(latlon);
        var iconcolor = google_map_item[i].iconColor;
        marker = new google.maps.Marker({
            map: map,
            position: latlon,
            icon: "https://chart.googleapis.com/chart?chst=d_map_pin_letter_withshadow&chld=" + (i + 1) + "|"+iconcolor+"|000000",
            type: 'flat',
            icon_color: '#ff0000', 
            label_color: '#ffffff', 
            width: '20', 
            height: '20', 
            label_size: '11',
                            clickable: true
        });

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

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

        map.fitBounds(bounds);
    }

However this only creates 1 info box that displays no matter which point you click.

但是,这只会创建 1 个信息框,无论您单击哪个点都会显示该信息框。

Thanks for any help

谢谢你的帮助

回答by Mathletics

Check out this blog post:

看看这篇博文:

http://you.arenot.me/2010/06/29/google-maps-api-v3-0-multiple-markers-multiple-infowindows/

http://you.arenot.me/2010/06/29/google-maps-api-v3-0-multiple-markers-multiple-infowindows/

Basically, you are overwriting each marker object with the new marker object. You need to make each marker context-specific, using this.

基本上,您是用新的标记对象覆盖每个标记对象。您需要使用this.

Your event listener should look like:

您的事件侦听器应如下所示:

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

You may need to make more changes to ensure you are creating new objects for each iteration. Try this and let us know!

您可能需要进行更多更改以确保为每次迭代创建新对象。试试这个,让我们知道!

回答by InterfaceGuy

Ahhhh, thisproblem....

啊啊啊这个问题……

It's a tough one if you don't know what you're looking for. I had this a few months back and it was terrifyingly hard to find the right answer, whether on StackOverflow or even in the Google Maps documentation.

如果您不知道自己在寻找什么,这将是一项艰巨的任务。几个月前我遇到了这个问题,无论是在 StackOverflow 还是在 Google Maps 文档中,都很难找到正确的答案。

I don't purport to know why this code works any more than the next man, but it worked for me, and with a little bit of tweaking on your part to fit your project, it should work for you too.

我并不想知道为什么这段代码比下一个人更有效,但它对我有用,并且你稍微调整一下以适应你的项目,它也应该对你有用。

Here is the code I used. There are a few artifacts from my project in there in terms of variable names, but I've tried to strip most of it out that I could, and comment out the parts which you don't need or which you can change based on your desired behavior of the InfoWindows.

这是我使用的代码。就变量名称而言,我的项目中有一些工件,但我已尝试将其中的大部分剥离出来,并注释掉您不需要的部分,或者您可以根据自己的情况进行更改的部分InfoWindows 所需的行为。

function initMap(){

    bldgNo =     new Object();  // YOU CAN GET
    bldgName =   new Object();  // RID OF ANY
    bldgAddr =   new Object();  // OF THESE...
    bldgGfx =    new Object();  // 
    mainMeter =  new Object();  // JUST REPLACE
    alarmCount = new Object();  // THEM WITH
    latitude =   new Object();  // WHAT YOU'LL
    longitude =  new Object();  // NEED INSTEAD.
    markersArray = [];

    google.maps.Map.prototype.clearOverlays = function() {
        if (markersArray) {
            for (i in markersArray) {
                markersArray[i].setMap(null);
            }
            markersArray.length = 0;
        }
    }

    location1 = new google.maps.LatLng(22.413543,-137.075743);  // IN CASE YOU'LL NEED MORE
    location2 = new google.maps.LatLng(22.628202,-137.426432);  // THAN ONE LOCATION? I DID.
    myOptions = {
        zoom:15,            // BEST IS BETWEEN 12-15
        scrollwheel:false,  // EITHER TRUE OR FALSE
        center:location1,   // ONE OF THE ABOVE LAT/LNG LOCATIONS
        mapTypeId: google.maps.MapTypeId.HYBRID // ROADMAP, SATELLITE, HYBRID, or TERRAIN (all-caps)
    };
    map =       new google.maps.Map(document.getElementById("map_canvas"),myOptions);
    icon =      new google.maps.MarkerImage('images/YOUR-IMAGE-HERE.png',new google.maps.Size(20,34),new google.maps.Point(0,0),new google.maps.Point(10,34));
    shadow =    new google.maps.MarkerImage('images/YOUR-SHADOW-IMG.png',new google.maps.Size(37,34),new google.maps.Point(0,0),new google.maps.Point(10,34));

    infowindow=new google.maps.InfoWindow();

    var i=1;

    $(".building").each(function(i){

        bldgNo[i] =     $(this).children(".bldg-no").html();        // YOU CAN GET
        bldgName[i] =   $(this).children(".bldg-name").html();      // RID OF ANY
        bldgAddr[i] =   $(this).children(".bldg-address").html();   // OF THESE...
        bldgGfx[i] =    $(this).children(".bldg-graphic").html();   // 
        mainMeter[i] =  $(this).children(".main-meter").html(); // JUST REPLACE
        alarmCount[i] = $(this).children(".alarm-count").html();    // THEM WITH
        latitude[i] =   $(this).children(".latitude").html();       // WHAT YOU'LL 
        longitude[i] =  $(this).children(".longitude").html();      // NEED INSTEAD.

        marker=new google.maps.Marker({
            position:new google.maps.LatLng(
                latitude[i],                        // (DEFINED ABOVE)
                longitude[i]                        // (DEFINED ABOVE)
            ),
            map:map,                                // THE DEFAULT
            shadow:shadow,                          // JUST MY NAME FOR IT (DEFINED ABOVE)
            icon:icon,                              // JUST MY NAME FOR IT (DEFINED ABOVE)
            title:bldgName[i]+" \n"+bldgAddr[i],    // FEEL FREE TO CHANGE THIS BASED ON WHAT YOU NEED
            optimized:false                         // YOU MAY OR MAY NOT NEED THIS
        });
        marker.setAnimation(google.maps.Animation.NULL); // NULL, DROP, or BOUNCE (all-caps)

        markersArray.push(marker);

        google.maps.event.addListener(marker,'click',(function(marker,i){
            return function(){
                infowindow.setContent('

                    //
                    // INSERT INFOWINDOW CONTENT HERE
                    //

                ');infowindow.open(map,marker);
            }
        })(marker,i));

        i++;

    });

}
function updateMap(){

    map.clearOverlays();
    infowindow=new google.maps.InfoWindow();
    var i=1;
    $(".building").each(function(i){

        bldgNo[i] =     $(this).children(".bldg-no").html();        // YOU CAN GET
        bldgName[i] =   $(this).children(".bldg-name").html();      // RID OF ANY
        bldgAddr[i] =   $(this).children(".bldg-address").html();   // OF THESE...
        bldgGfx[i] =    $(this).children(".bldg-graphic").html();   // 
        mainMeter[i] =  $(this).children(".main-meter").html(); // JUST REPLACE
        alarmCount[i] = $(this).children(".alarm-count").html();    // THEM WITH
        latitude[i] =   $(this).children(".latitude").html();       // WHAT YOU'LL 
        longitude[i] =  $(this).children(".longitude").html();      // NEED INSTEAD.

        marker=new google.maps.Marker({
            position:new google.maps.LatLng(
                latitude[i],                        // (DEFINED ABOVE)
                longitude[i]                        // (DEFINED ABOVE)
            ),
            map:map,                                // THE DEFAULT
            shadow:shadow,                          // JUST MY NAME FOR IT (DEFINED ABOVE)
            icon:icon,                              // JUST MY NAME FOR IT (DEFINED ABOVE)
            title:bldgName[i]+" \n"+bldgAddr[i],    // FEEL FREE TO CHANGE THIS BASED ON WHAT YOU NEED
            optimized:false                         // YOU MAY OR MAY NOT NEED THIS
        });
        marker.setAnimation(google.maps.Animation.NULL); // NULL, DROP, or BOUNCE (all-caps)

        markersArray.push(marker);
        google.maps.event.addListener(marker,'click',(function(marker,i){
            return function(){
                infowindow.setContent('

                    //
                    // INSERT UPDATED INFOWINDOW CONTENT HERE
                    //

                ');infowindow.open(map,marker);
            }
        })(marker,i));

        i++;

    });

}

I'm sure some kinks will need to be worked out of that, but the code I have on my computer (the version not edited for your benefit) works like a charm. If I've mistakenly made any breaks in the code when copying it over and editing it for your ease of use, just let me know and I'll update my answer.

我确定需要解决一些问题,但是我计算机上的代码(未为您的利益进行编辑的版本)非常有用。如果我在复制代码并对其进行编辑以方便您使用时错误地中断了代码,请告诉我,我会更新我的答案。

Cheers!

干杯!





Edit:By the way, this code both creates the hidden info windows (the initMapfunction) and updates the hidden info windows (the updateMapfunction). If you call the updateMapfunction at set intervals, it updates the information in your map, which was necessary for my project.

编辑:顺便说一下,这段代码既创建了隐藏的信息窗口(initMap函数),又更新了隐藏的信息窗口(updateMap函数)。如果您按updateMap设定的时间间隔调用该函数,它会更新地图中的信息,这对我的项目来说是必需的。

As such, there are code blocks which are very similar/duplicated, because I needed to delete the hidden blocks and create new ones each time the page's InfoWindows updated.

因此,存在非常相似/重复的代码块,因为每次更新页面的 InfoWindows 时,我都需要删除隐藏的块并创建新的块。

You can simplify it to your needs very easily by deleting the updateMapfunction and any artifacts in initMapwhich were created solely for manipulation in updateMap. Then just call the initMapfunction and you're all set!

您可以通过删除updateMap函数和任何initMap专为在updateMap. 然后只需调用该initMap函数即可!

回答by geocodezip

From the suggestions on the right: Google Maps API v3 adding an InfoWindow to each marker

来自右侧的建议: Google Maps API v3 向每个标记添加一个 InfoWindow

Seems to be the answer you are looking for (using function closure).

似乎是您正在寻找的答案(使用函数闭包)。

Working example, infowindow content from xml

工作示例,来自 xml 的信息窗口内容

回答by wayfare

I believe the common practice when dealing with InfoWindow is to make a global window and bind it to click event with each marker, instead of making one for each marker. I made to make a simple app with google markers and this is what I used. Hope this helps!

我相信处理 InfoWindow 时的常见做法是创建一个全局窗口并将其绑定到每个标记的 click 事件,而不是为每个标记创建一个。我用谷歌标记制作了一个简单的应用程序,这就是我使用的。希望这可以帮助!

    var globalInfoWindow = new google.maps.InfoWindow();
    var offset = new google.maps.Size(17,-10);
    globalInfoWindow.setOptions({pixelOffset: offset});

    .
    .
    .        

    for(var i in data.locations)
    {
      var latlng = data.locations[i];

      var lat = Number(latlng[0]);
      var lng = Number(latlng[1]);

      var marker_latlng = new google.maps.LatLng(lat, lng);
      var marker = new google.maps.Marker({
        position: marker_latlng,
        icon: markerImg,
        map: map
      });


    // binds the showing of infowindow with click event.

      google.maps.event.addListener(marker, 'click', viewLocPic);
    }

    .
    .
    .
    // 'this' in the function refers to the marker itself.
    function viewLocPic()
    {
      console.log("this refers to " + this);
      globalInfoWindow.setPosition(this.getPosition());
      globalInfoWindow.setContent("<img src='cycling.png'/>");
      globalInfoWindow.open(map, this);
    }