简体   繁体   中英

multiple markers with unique infowindows using google maps javascript api v3

I know this question is posted all over stack overflow. But I've been working at it for days, and none of the solutions have worked. I'll post everything I'm doing and maybe someone will see my mistake. I'd much rather leave comments on the other existing questions but there is a requirement of 50 rep... I hope there are enough comments to help you read the code but let me summarize. I have the initialize function for the map. Since my maps is about directions there is a calcRoute() function. This function gets a route from google, and puts in on the map. I also place some markers along the route, that's the parksToPlaceArray. so if the ajax returns successfully I parse through the data and add the markers. and just below creating the marker I have attempted to add an event listener for the infowindow, but it does not work. I'd like to get a concept going because I would like to have a title, small description, maybe a thumbnail, and have the title link to the details page.

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

I've tried a few different places to put the event listener. I can't really put it in the initialize since the actual markers are brought in using ajax. I have a list of locations 'parksToPlaceArray' and I loop through it creating a marker and placing it. Everything works except for the ability to click on a marker.

EDIT: So I made a change based on the comments, and now clicking any marker shows one infowindow over a single item. Any marker click will show the same single info window over the same marker

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

                        } 

To clarify: you want to know how to close the other info windows when you click on a marker.

The answer is to use a single info window. So you were closer with your original code.

To make the original code work you should write your for loop like this (because there is a function closure inside the loop)

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

So you should write

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

I believe your issue is in the way you are handling the infowindows. You should be following a pattern along the lines of:

  1. Create a marker for each point (park)
  2. Create an infowindow with the desired content for the marker
  3. Add the infowindow to the marker
  4. Add an event handler for the marker that opens the infowindow you added to it.

What you are doing is:

  1. Create a single infowindow
  2. Create a marker for each point (park)
  3. Add an event handler for each marker that opens the single infowindow that isn't attacked to anything.

Try Modifying:

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

To something along the lines of:

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

Ok I got it with help from the comment

The problem was setting up an infowindow for the marker as a property, and the event listener used this instead of marker. Here are the changes I made, and I removed the global infowindow entirely

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM