【问题标题】:multiple markers with unique infowindows using google maps javascript api v3使用谷歌地图javascript api v3具有独特信息窗口的多个标记
【发布时间】:2015-07-23 16:38:56
【问题描述】:

我知道这个问题是通过堆栈溢出发布的。但是我已经为此工作了好几天,但没有一个解决方案奏效。我会发布我正在做的所有事情,也许有人会看到我的错误。我宁愿将 cmets 留在其他现有问题上,但需要 50 个代表...我希望有足够的 cmets 可以帮助您阅读代码,但让我总结一下。我有地图的初始化功能。因为我的地图是关于方向的,所以有一个 calcRoute() 函数。这个函数从谷歌获取一条路线,并放在地图上。我还在路线上放置了一些标记,即 parksToPlaceArray。因此,如果 ajax 成功返回,我会解析数据并添加标记。在创建标记的下方,我试图为信息窗口添加一个事件侦听器,但它不起作用。我想要一个概念,因为我想要一个标题、小描述,也许是一个缩略图,并有一个指向详细信息页面的标题链接。

    var directionsDisplay;
    var directionsService = new google.maps.DirectionsService();
    var map;
    var infowindow;
    var parksToPlaceArray = [];

    function initialize() {
        directionsDisplay = new google.maps.DirectionsRenderer();
        var desoto = new google.maps.LatLng(27.521692, -82.643475); // just a default start value to the map
        var mapOptions = {
            zoom: 15,
            center: desoto
        };


        map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
        directionsDisplay.setMap(map);

        // Resize stuff...
        // makes the map responsive by continuously centering the map on resize
        google.maps.event.addDomListener(window, "resize", function () {
            var center = map.getCenter();
            google.maps.event.trigger(map, "resize");
            map.setCenter(center);
        });

        infowindow = new google.map.InfoWindow();

        // marker click
        //google.maps.event.addListener(marker, 'click', function () {
        //    //map.setZoom(8);
        //    //map.setCenter(marker.getPosition());
        //});


    }

    function calcRoute() {
        var start = document.getElementById('start').value;
        var end = document.getElementById('end').value;
        var request = {
            origin: start,
            destination: end,
            travelMode: google.maps.TravelMode.DRIVING
        };

        directionsService.route(request, function (response, status) {
            if (status == google.maps.DirectionsStatus.OK) {
                directionsDisplay.setDirections(response);




                // This ajax call goes out to loadparksbyroute.cshtml with the bounds of the route, and returns a json array of possible parks
                $.ajax({
                    dataType: "json",
                    type: "POST",
                    url: "/getDataPage",
                    success: function (ajaxResponse) {

                        // SUCCESS FUNCTION - RETURNED FROM AJAX ==================================================================


                        var parksResponse = ajaxResponse;
                        // we now have a list of all locations in the zone

                        parksToPlaceArray = getParks();



                        for (i = 0; i < parksToPlaceArray.length; i++) {
                            var myLatlng = new google.maps.LatLng(parksToPlaceArray[i].addresses[0].latitude, parksToPlaceArray[i].addresses[0].longitude);

                            var marker = new google.maps.Marker({
                                position: myLatlng,
                                map: map,
                                title: parksToPlaceArray[i].recAreaName 
                            });

                            //google.maps.event.addListener(marker, 'click', (function (marker, i) {
                            //    return function () {
                            //        infowindow.setContent('<h3>' + this.title + '</h3>');
                            //        infowindow.open(map, marker);
                            //    }
                            //})(marker, i));

                            google.maps.event.addListener(marker, 'click', function () {
                                infowindow.setContent('<h3>' + this.title + '</h3>');
                                infowindow.open(map, this);
                            });

                        }


                    },
                    // END OF SUCCESS FUNCTION FROM AJAX CALL
                    error: function (response) {
                        console.log('error');
                    }
                });


            }
        });


    }

    // when the page loads initialize the map
    google.maps.event.addDomListener(window, 'load', initialize);

我尝试了几个不同的地方来放置事件监听器。我不能真正把它放在初始化中,因为实际的标记是使用 ajax 引入的。我有一个位置列表“parksToPlaceArray”,我遍历它创建一个标记并放置它。除了能够点击标记之外,一切正常。

编辑:所以我根据 cmets 进行了更改,现在单击任何标记会在单个项目上显示一个信息窗口。任何标记点击都会在同一标记上显示相同的单个信息窗口

for (i = 0; i < parksToPlaceArray.length; i++) {
                            var myLatlng = new google.maps.LatLng(parksToPlaceArray[i].addresses[0].latitude, parksToPlaceArray[i].addresses[0].longitude);

                            var marker = new google.maps.Marker({
                                position: myLatlng,
                                map: map,
                                title: parksToPlaceArray[i].recAreaName 
                            });

                            //google.maps.event.addListener(marker, 'click', (function (marker, i) {
                            //    return function () {
                            //        infowindow.setContent('<h3>' + this.title + '</h3>');
                            //        infowindow.open(map, marker);
                            //    }
                            //})(marker, i));

                            var contentString = parksToPlaceArray[i].recAreaName;
                            marker.infowindow = new google.maps.InfoWindow({
                                content: contentString
                            });

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

                        } 

【问题讨论】:

  • 请提供一个Minimal, Complete, Tested and Readable example 来证明问题中的问题。
  • 我正在尝试使用 jsfiddle。但是,如果大部分问题可能出在本地运行的 ajax 调用中,我该如何实现一个小示例。我可以为 parksToPlaceArray 设置虚拟值,但我不想删除 ajax,让它工作,然后当我真正实现它时,我遇到了所有相同的问题,而且你需要一个用于谷歌地图的 api 密钥我不想发帖

标签: javascript ajax google-maps google-maps-api-3


【解决方案1】:

澄清一下:您想知道如何在单击标记时关闭其他信息窗口。

答案是使用单个信息窗口。所以你更接近你的原始代码。

要使原始代码正常工作,您应该像这样编写 for 循环(因为循环内有一个函数闭包)

for (i = 0; i < parksToPlaceArray.length; i++) (function(i) {
    // ...
})(i);

所以你应该写

for (i = 0; i < parksToPlaceArray.length; i++) (function(i) {
    var myLatlng = new google.maps.LatLng(
        parksToPlaceArray[i].addresses[0].latitude,
        parksToPlaceArray[i].addresses[0].longitude);

    var marker = new google.maps.Marker({
        position: myLatlng,
        map: map,
        title: parksToPlaceArray[i].recAreaName 
    });

    marker.addListener('click', function() {
        infowindow.setContent('<h3>' + marker.title + '</h3>');
        infowindow.open(map, marker);
    });
})(i);

【讨论】:

    【解决方案2】:

    我相信您的问题在于您处理信息窗口的方式。您应该遵循以下模式:

    1. 为每个点(公园)创建一个标记
    2. 为标记创建一个包含所需内容的信息窗口
    3. 将信息窗口添加到标记
    4. 为打开您添加到其中的信息窗口的标记添加一个事件处理程序。

    你正在做的是:

    1. 创建单个信息窗口
    2. 为每个点(公园)创建一个标记
    3. 为每个打开单个信息窗口的标记添加一个事件处理程序,该信息窗口不会受到任何攻击。

    尝试修改:

    var marker = new google.maps.Marker({
                                    position: myLatlng,
                                    map: map,
                                    title: parksToPlaceArray[i].recAreaName 
                                });
    
    
    google.maps.event.addListener(marker, 'click', function () {
                                    infowindow.setContent('<h3>' + this.title + '</h3>');
                                    infowindow.open(map, this);
                                });
    

    大致如下:

    var marker = new google.maps.Marker({
                                    position: myLatlng,
                                    map: map,
                                    title: parksToPlaceArray[i].recAreaName 
                                });
    
    marker.infowindow = new google.maps.InfoWindow({ content: '<h3>' + this.title + '</h3>' }); 
    
    google.maps.event.addListener(marker, 'click', function () {   
                                    this.infowindow.open(map, this);          
                                });
    

    【讨论】:

    • 哦,我想我看到您将点击事件置于创建标记的范围内,对吗?因为是的,我绝对明白我在做什么并没有真正连接任何东西。
    • marker.infowindow = new google.maps.InfoWindow({ '

      ' + this.title + '

      ' }); 上似乎存在语法错误第一个加号表示预期的“:”,所以我无法测试新方法
    • 糟糕,这应该是new google.maps.InfoWindow({ content: '&lt;h3&gt;' + this.title + '&lt;/h3&gt;' }); 我的错。 @亚历克斯
    • 是的,我查找了 InfoWindow 的构造函数。因此,我使用您的示例对帖子进行了编辑,并解释了结果。所有标记在其中一个标记上只有一个信息窗口
    • 我编辑了我的答案并修复了关闭问题,对此感到抱歉...此外,如果您只想一次打开一个窗口,只需添加一个全局 var lastopened; infowindow 变量并在标记的事件侦听器中首先调用lastopened.close() 然后lastopened = this.infowindow; 然后像正常一样打开信息窗口。只需确保在调用 lastopened.close() 之前进行空检查。 @亚历克斯
    【解决方案3】:

    好的,我在评论的帮助下得到了它

    问题是为标记设置一个信息窗口作为属性,而事件侦听器使用它而不是标记。这是我所做的更改,我完全删除了全局信息窗口

    var contentString = '<h3>' + parksToPlaceArray[i].recAreaName + '</h3>';
    var infowindow = new google.maps.InfoWindow({
        content: contentString
    });
    
        var marker = new google.maps.Marker({
            position: myLatlng,
            map: map,
            title: parksToPlaceArray[i].recAreaName,
            infowindow: infowindow
        });
    
        google.maps.event.addListener(marker, 'click', function () {   
           this.infowindow.open(map, this);          
        });
    

    【讨论】:

    • 现在我只需要弄清楚当我点击一个信息窗口时如何关闭其他信息窗口,就可以了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-16
    • 2013-07-02
    • 2015-01-14
    • 2013-05-18
    • 2013-06-28
    • 2013-10-04
    相关资源
    最近更新 更多