多个地理编码器请求后的Google Maps API v3 - fitBounds

时间:2012-07-04 23:42:57

标签: google-maps-api-3

我想要做的是使用AJAX和JSON加载一堆地址,找出每个地址的纬度和经度,在地图上放置标记,然后使用fitBounds()放大,以便所有标记都是可见。听起来很简单。

我已经把大部分内容打包了,但我的问题是fitBounds()部分。

基本上似乎正在发生的是在循环遍历每个地址并找到纬度和经度时,它似乎在循环下加载fitBounds()函数。

所以它正在调用fitBounds()但是marker_bounds数组中还没有任何内容。我原本以为它会在到达fitBounds()函数之前完成循环,但我想geocoder.geocode()函数必须使它在确定纬度和经度时继续加载其余的JavaScript。

我的代码如下:

var geocoder;
var map;
var marker_bounds = [];

var myOptions = {
    zoom: 12,
    mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);    

$.post('addresses.php', function(data) {

    var next_filter = '';           
    for(var x=0;x<data.addresses.length;x++) {

        geocoder.geocode( { 'address': data.addresses[x].address}, function(results, status) {

            if (status == google.maps.GeocoderStatus.OK) {

                marker = new google.maps.Marker({
                    map: map,
                    position: results[0].geometry.location
                });

                var latLng = new google.maps.LatLng(results[0].geometry.location.lat(), results[0].geometry.location.lng());
                marker_bounds.push(latLng);             
            }

        });             
    }

    var latlngbounds = new google.maps.LatLngBounds();
    for ( var i = 0; i < marker_bounds.length; i++ ) {
       latlngbounds.extend(marker_bounds[i]);
    }
    map.setCenter(latlngbounds.getCenter());
    map.fitBounds(latlngbounds); 

}, 'json'); 

在完成所有地理编码后,是否有可以调用的功能?

3 个答案:

答案 0 :(得分:7)

好的,这就是我所学到的。

  1. 地理编码方法进行异步调用,因此地理编码方法所在的页面将在地理编码器完成该过程中查找地址之前很久就完成。
  2. 您需要在运行地理编码方法后调用函数(addressBounds)并计算地理编码的地址数(address_count)。
  3. 每次调用addressBounds函数时,请检查是否已查找所有地址(if (total_addresses == address_count)),然后运行fitBounds()函数。
  4. 我的最终代码

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

答案 1 :(得分:2)

使用其他变量在 top 的全局范围内定义边界对象的简单方法,然后根据找到的每个结果构建它(在地理编码器回调内)。 / p>

基本上,你想要用回调数据做的一切都需要在回调中或由回调触发的函数(如你所发现的那样)。但在这种情况下,您不需要单独的功能。浏览器应存储所有fitBounds个操作,并仅执行最后一个操作。

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

如果有必要(因为您的浏览器足够快,可以为每个地址执行fitBounds),您可以跟踪在另一个变量中实际返回的结果数量,例如address_count和在执行fitBounds之前测试您是否拥有所有结果。也就是说,您的附属功能可以合并到地理编码器回调中。

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

答案 2 :(得分:0)

我知道以下并不是严格相关的,但我已经在这方面苦苦挣扎了一段时间,我认为值得分享。 在使用DirectionsRenderer渲染多个方向请求之后,地图通常集中在最后一个渲染命令的结果上,尽管事实上我在发出最后一个渲染命令后发出了map.fitBounds并带有一个边界框以包含所有方向请求结果视。行为不是确定性的,有时视口集中在整个地图上,有时候是最后一个方向请求结果。解决方案是为渲染器设置preserveViewport:true,因此在显示方向请求结果后它永远不会更改地图的焦点,所以现在我可以使用fitbounds更改焦点。