4

我想要做的是使用 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'); 

在所有地理编码完成后,我可以调用一个函数吗?

4

3 回答 3

7

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

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

我的最终代码

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);
    }
}
于 2012-07-05T02:27:59.240 回答
2

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

基本上,您想要对回调数据执行的所有操作都需要在回调中或由回调触发的函数中(如您所见)。但在这种情况下,您不需要单独的功能。浏览器应该存储所有的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);
于 2012-07-05T07:12:42.513 回答
0

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

于 2012-09-17T15:07:37.497 回答