Google Maps API v3 - fitBounds after multiple geocoder requests

前端 未结 3 2003
醉话见心
醉话见心 2021-01-03 05:12

What I want to do is load a bunch of addresses using AJAX and JSON, find out the latitude and longitude of each address, put markers on the map and then use fitBounds(

相关标签:
3条回答
  • 2021-01-03 05:50

    I know that the following is not strictly related, but I've been struggling with this for quite a while, and I think it's worth sharing. After rendering multiple direction requests with DirectionsRenderer, the map was focused usually on the result of the last render command, despite the fact that I issued map.fitBounds after issuing the last render command with a bounding box to include all the direction request results in the viewport. The behaviour was not deterministic, sometimes the viewport was focused on the entire map, sometimes on the last direction request result. The solution was to set the preserveViewport:true for the renderer, so it never changes the focus of the map after displaying a direction request result, so now I'm able to change the focus with the fitbounds.

    0 讨论(0)
  • 2021-01-03 06:06

    Ok, here's what I've learned.

    1. The geocode method makes an asynchonous call so the page that the geocode method is in will finish long before the geocoder is done looking up addresses during that process.
    2. You need to call a function (addressBounds) after the geocode method is run and count how many addresses it has geocoded (address_count).
    3. Each time the addressBounds function is called, check to see if all addresses have been looked up (if (total_addresses == address_count)), then run the fitBounds() function.

    My final code

    var geocoder;
    var map;
    var markerBounds = [];  
    
    var myOptions = {
        zoom: 4,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    }   
    map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);    
    
    google.maps.event.addListenerOnce(map, 'idle', function(){
    
        $.post('addresses.php', function(data) {
    
            var total_addresses = data.addresses.length;            
            var address_count = 0;
            for(var x=0;x<total_addresses;x++) {    
    
                geocoder.geocode( { 'address': data.addresses[x].address }, function(results, status) {
    
                    address_count++;        
    
                    if (status == google.maps.GeocoderStatus.OK) {
    
                        marker = new google.maps.Marker({
                            map: map,
                            position: results[0].geometry.location
                        });
    
                        var infowindow = new google.maps.InfoWindow();
                        infowindow.setContent(address);
                        google.maps.event.addListener(marker, 'click', function() {
                            infowindow.open(map, marker);
                        });
    
                        var myLatLng = new google.maps.LatLng(results[0].geometry.location.lat(), results[0].geometry.location.lng());                      
                        addressesBounds(total_addresses, address_count, myLatLng);  
    
                    }
    
                });
    
            }
    
        }, 'json');
    
    });
    
    function addressesBounds(total_addresses, address_count, myLatLng) {
    
        markerBounds.push(myLatLng);
    
        // make sure you only run this function when all addresses have been geocoded
        if (total_addresses == address_count) {
            var latlngbounds = new google.maps.LatLngBounds();
            for ( var i = 0; i < markerBounds.length; i++ ) {
               latlngbounds.extend(markerBounds[i]);
            }
            map.setCenter(latlngbounds.getCenter());
            map.fitBounds(latlngbounds);
        }
    }
    
    0 讨论(0)
  • 2021-01-03 06:09

    The easy way of doing it to define your bounds object in global scope at the top with the other variables, and then construct it with each result as it's found (inside the geocoder callback).

    Basically, everything you want to do with callback data needs to be in the callback or a function triggered by the callback (as you found). But in this case you don't need a separate function. The browser should store up all the fitBounds operations and do only the last one.

    var latLng = new google.Maps.LatLng(
                              results[0].geometry.location.lat(),
                              results[0].geometry.location.lng());
    marker_bounds.push(latLng);
    latlngbounds.extend(latLng);
    map.fitBounds(latlngbounds);
    

    If necessary (because your browser is fast enough to do the fitBounds for every address), you could keep track of how many results have actually been returned in another variable, like your address_count, and test whether you have all the results before doing the fitBounds. That is, your subsidiary function can be incorporated into the geocoder callback.

    var latLng = new google.Maps.LatLng(
                              results[0].geometry.location.lat(),
                              results[0].geometry.location.lng());
    marker_bounds.push(latLng);
    latlngbounds.extend(latLng);
    address_count++;
    if (address_count == data.addresses.length) map.fitBounds(latlngbounds);
    
    0 讨论(0)
提交回复
热议问题