简体   繁体   中英

Google places API place multiple markers on the map and zoom to where most markers are

First I want to show you what solutions I have already tried, so you guys don't use them either:

  1. placing multiple markers on google map from array .
  2. placing multiple markers on a google map .

As I have the following loop through the places:

service.textSearch({query:query}, function(results, status) {
    if (status == google.maps.places.PlacesServiceStatus.OK) {
        //for each result in results.length ++
        for (var i = 0; i < results.length; i++) {
            //here I'm just setting the names from the variables into a list, to display the names as I show in (Figure 1).
            var item = document.createElement('li');
            item.appendChild(document.createTextNode(results[i].name));
            document.getElementById('results').appendChild(item);

            //here I set my variables that are necessary for the markers to work
            p_id[i] = results[i].place_id;

            lat[i] = results[i].geometry.location.lat();
            lng[i] = results[i].geometry.location.lng();

            //here I initialize the map with the given values.
            initMap(p_id, lat, lng, i);
        }
    }
});

图1


As this loop completes it goes to where it places the markers on the map.

I don't want to get rid of the places that it creates again, as it's very useful for me to have, plus it doesn't seem to obstruct what I try to make. 我不想摆脱它再次创建的places ,因为它对我来说非常有用,而且它似乎也不会阻碍我尝试做的事情。

As for the marker placer on the map itself:

function initMap(p_id, lat, lng, i) {
    //this creates the position of the map
    var map = new google.maps.Map(document.getElementById('map'), {
        center: {lat: lat[i], lng: lng[i]},
        zoom: 13
    });

    var infowindow = new google.maps.InfoWindow(), marker, i;
    var service = new google.maps.places.PlacesService(map);

    var marker;

    //gets the details of the placeid over again
    service.getDetails({
        placeId: p_id[i]
    }, function(place, status) {
        if (status === google.maps.places.PlacesServiceStatus.OK) {

            //this is where the marker is created with position and animation
            marker = new google.maps.Marker({
                animation: google.maps.Animation.DROP,
                position: new google.maps.LatLng(lat[i], lng[i]),
                map: map
            });

            //this is the info if you click the marker
            google.maps.event.addListener(marker, 'click', (function(marker, i) {
                return function() {
                    infowindow.setContent('<div><strong>' + place.name + '</strong><br>' + 'Place ID: ' + place.place_id + '<br>' + place.formatted_address + '</div>');
                    infowindow.open(map, marker);
                }
            })(marker, i));
        }
    });
}

Strangely enough if there's only 1 place, then 1 marker shows up, but when they have more places, then there are no markers at all... as I show in


图2


If anyone has any clues to solve it, please tell them. I can't seem to figure it out myself sadly, though I have been searching for a while now. I tried to make a Jsfiddle, but sadly the API is not able to run on jsfddle...


The multiple marker problem was solved by SeanKendle . The problem was like I already suspected that I kept creating multiple maps...

I simply moved the maps out of my mapinit function and placed it above my service in the getPlaces function like this:

var map = new google.maps.Map(document.getElementById('map'), {
    center: latlng,
    zoom: 5
});

service = new google.maps.places.PlacesService(
  document.getElementById('attributions') //attributions-container
);

//send a query
service.textSearch({query:query}, function(results, status) {
    if (status == google.maps.places.PlacesServiceStatus.OK) {
        for (var i = 0; i < results.length; i++) {
            var item = document.createElement('li');
            item.appendChild(document.createTextNode(results[i].name));
            document.getElementById('results').appendChild(item);

            p_id[i] = results[i].place_id;

            lat[i] = results[i].geometry.location.lat();
            lng[i] = results[i].geometry.location.lng();

            initMap(p_id, lat, lng, i, map);
        }
    }
});

Now the last problem I'm facing is that I need to zoom in at the place with the most markers. Now I just simply set the lat and long where it should start as this:

var latlng = new google.maps.LatLng(20.540221, -4.042969);

Already thanks in advance!


Please read my comments carefully. I may have missed a few things, I'm in a rush doing this at work. I've simplified a lot of your code and removed some extra service calls, etc.

Edit: I've added a map bounds variable to set the map zoom and center after placing markers

Edit 2: I've added a Google Maps callback function to eliminate the race condition that left you without access to the google namespace. Be sure to replace YOUR_API_KEY

First, move the actual map initialization out of the loop:

<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"
    async defer></script>

<script>
    var startLatLng, //change this to some value near to where the map will end up
        allMarkers = [], //keep a global copy of your markers
        mapPointsBounds = [], //map bounds of all markers
        map; //copy of the map

    //Google will call this when it's ready, it's a query string in the script tag above `&callback=initMap`:
    function initMap() {
        startLatLng = new google.maps.LatLng([0, 0]);
        mapPointsBounds = new google.maps.LatLngBounds();

        map = new google.maps.Map(document.getElementById('map'), {
            center: startLatLng,
            zoom: 13
        });

        service.textSearch({query:query}, function(results, status) {
            if (status == google.maps.places.PlacesServiceStatus.OK) {
                //for each result in results.length ++
                for (var i = 0; i < results.length; i++) {
                    //here I'm just setting the names from the variables into a list, to display the names as I show in (Figure 1).
                    var item = document.createElement('li');
                    item.appendChild(document.createTextNode(results[i].name));
                    document.getElementById('results').appendChild(item);

                    //let's just send the object, this is unnecessary:
                    //here I set my variables that are necessary for the markers to work
                    //p_id[i] = results[i].place_id;
                    //lat[i] = results[i].geometry.location.lat();
                    //lng[i] = results[i].geometry.location.lng();

                    //Change this function name to "addMapMarker", send in the results object
                    addMapMarker(results[i], i);
                }

                //finally, fitBounds on map to set zoom and center:
                map.fitBounds(mapPointsBounds);
            }
        });
    }

    //I would change the name of this function to "addMapMarker" or something similar
    function addMapMarker(markerInfo, i) {
        //why are you initializing "i" again if you're passing it in?
        var infowindow = new google.maps.InfoWindow(), marker; //, i;
        var service = new google.maps.places.PlacesService(map);

        var marker;

        //gets the details of the placeid over again - why?  Why not send the info into the function?
        /* Is this really necessary again?
        service.getDetails({
            placeId: markerInfo.place_id
        }, function(place, status) {
            if (status === google.maps.places.PlacesServiceStatus.OK) {
        */
        //this is where the marker is created with position and animation
        marker = new google.maps.Marker({
            animation: google.maps.Animation.DROP,
            position: markerInfo.geometry.location,
            map: map,
            markerInfo: markerInfo //you can store anything in the map point
        });

        allMarkers.push(marker); //keeping all markers in an array
        mapPointsBounds.extend(markerInfo.geometry.location); //extend bounds to contain this marker


        //this is the info if you click the marker
        //you're running a function, then returning a function... just put a simple function here:
        google.maps.event.addListener(marker, 'click', function (marker, i) {
            //return function() {
            infowindow.setContent('<div><strong>' + marker.markerInfo.name + '</strong><br>' + 'Place ID: ' + marker.markerInfo.place_id + '<br>' + marker.markerInfo.formatted_address + '</div>');
            infowindow.open(map, marker);
            //}
        });
    }
</script>

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