从地理编码结果中获取城市信息?

45

在处理地理编码结果时,无法获取不同数组的内容。

item.formatted_address 可以正常工作,但 item.address_components.locality 不能正常工作?

geocoder.geocode( {'address': request.term }, function(results, status) {

        response($.map(results, function(item) {

        alert(item.formatted_address+" "+item.address_components.locality)
    }            
}); 

// 返回的数组是:

 "results" : [
      {
         "address_components" : [
            {
               "long_name" : "London",
               "short_name" : "London",
               "types" : [ "locality", "political" ]
            } ],
          "formatted_address" : "Westminster, London, UK" // rest of array...

非常感谢任何帮助!

Dc

15个回答

60

最终使用以下方法解决问题:

var arrAddress = item.address_components;
var itemRoute='';
var itemLocality='';
var itemCountry='';
var itemPc='';
var itemSnumber='';

// iterate through address_component array
$.each(arrAddress, function (i, address_component) {
    console.log('address_component:'+i);

    if (address_component.types[0] == "route"){
        console.log(i+": route:"+address_component.long_name);
        itemRoute = address_component.long_name;
    }

    if (address_component.types[0] == "locality"){
        console.log("town:"+address_component.long_name);
        itemLocality = address_component.long_name;
    }

    if (address_component.types[0] == "country"){ 
        console.log("country:"+address_component.long_name); 
        itemCountry = address_component.long_name;
    }

    if (address_component.types[0] == "postal_code_prefix"){ 
        console.log("pc:"+address_component.long_name);  
        itemPc = address_component.long_name;
    }

    if (address_component.types[0] == "street_number"){ 
        console.log("street_number:"+address_component.long_name);  
        itemSnumber = address_component.long_name;
    }
    //return false; // break the loop   
});

5
功能良好,但使用“switch”语句可以使代码更加优雅简洁。 - Grant
4
不要指望这个能够可靠地工作,谷歌的地理编码在很多方面有缺陷。 "locality"(市)并不总是可用的,有时城市实际上在州(level_1)字段中。特别是当返回类型为ROOFTOP时,谷歌地理编码的结果很糟糕。在国外,它们突然切换格式。您可以更信任“APPROXIMATE”(大致)结果而不是“ROOFTOP”。 - John
正确。不可靠。Google指出,响应中获取的组件没有一致性。而且这可能会随着时间的推移而改变。https://developers.google.com/maps/documentation/places/web-service/details 在“地点详细信息结果”下。 - bjornl

15

尝试了几个不同的请求:

MK107BX

Cleveland Park Crescent, UK

如你所说,返回的数组大小不一致,但是两个结果的城镇名称似乎都在地址组件项中,类型为[“locality”,“political”]。也许您可以将其用作指示器?

编辑: 使用jQuery获取locality对象,请将以下内容添加到您的response函数中:

var arrAddress = item.results[0].address_components;
// iterate through address_component array
$.each(arrAddress, function (i, address_component) {
    if (address_component.types[0] == "locality") // locality type
        console.log(address_component.long_name); // here's your town name
        return false; // break the loop
    });

1
不确定为什么会这样,因为没有针对“addresses”的变量/数组。 - v3nt
抱歉,我说的是不同的谷歌地图API请求。已编辑。 - Ruslan
不用担心!你有任何想法怎样获取地区信息吗?我的尝试中只能得到undefined的结果;-/ 如果item.formatted_address可用的话,那么我认为使用item.address_components.locality也应该可以,这个想法错了吗? - v3nt
不行,因为formatted_address是一个字符串,而address_components是一个数组。我会添加代码来查看它。 - Ruslan
1
在你的代码中,第一行可能是 var arrAddress = item.address_components;。但是你的代码无法运行,因为 address_components 是一个数组。 - Ruslan
运行得很好。使用'.short_name',我终于收到了不带', Country'后缀的城市名。谢谢! - kosemuckel

11

我不得不创建一个程序,当用户在地图上单击某个位置时,该程序将填写用户表单中的纬度、经度、城市、县和州字段。此页面可在http://krcproject.groups.et.byu.net找到,并且是一个用户表单,允许公众向数据库做出贡献。我不自诩为专家,但它运行得很好。

<script type="text/javascript">
  function initialize() 
  {
    //set initial settings for the map here
    var mapOptions = 
    {
      //set center of map as center for the contiguous US
      center: new google.maps.LatLng(39.828, -98.5795),
      zoom: 4,
      mapTypeId: google.maps.MapTypeId.HYBRID
    };

    //load the map
    var map = new google.maps.Map(document.getElementById("map"), mapOptions);

    //This runs when the user clicks on the map
    google.maps.event.addListener(map, 'click', function(event)
    {
      //initialize geocoder
      var geocoder = new google.maps.Geocoder()

      //load coordinates into the user form
      main_form.latitude.value = event.latLng.lat();
      main_form.longitude.value = event.latLng.lng();

      //prepare latitude and longitude
      var latlng = new google.maps.LatLng(event.latLng.lat(), event.latLng.lng());

      //get address info such as city and state from lat and long
      geocoder.geocode({'latLng': latlng}, function(results, status) 
      {
        if (status == google.maps.GeocoderStatus.OK) 
        {
          //break down the three dimensional array into simpler arrays
          for (i = 0 ; i < results.length ; ++i)
          {
            var super_var1 = results[i].address_components;
            for (j = 0 ; j < super_var1.length ; ++j)
            {
              var super_var2 = super_var1[j].types;
              for (k = 0 ; k < super_var2.length ; ++k)
              {
                //find city
                if (super_var2[k] == "locality")
                {
                  //put the city name in the form
                  main_form.city.value = super_var1[j].long_name;
                }
                //find county
                if (super_var2[k] == "administrative_area_level_2")
                {
                  //put the county name in the form
                  main_form.county.value = super_var1[j].long_name;
                }
                //find State
                if (super_var2[k] == "administrative_area_level_1")
                {
                  //put the state abbreviation in the form
                  main_form.state.value = super_var1[j].short_name;
                }
              }
            }
          }
        }
      });
    });
  }
</script>

我喜欢这个,谢谢你,唯一建议的是可能需要一个检查/中断,以便在找到组件时停止搜索。 - luke_mclachlan

7
我假设您想获取城市和州/省份信息:
var map_center = map.getCenter();
reverseGeocode(map_center);


function reverseGeocode(latlng){
  geocoder.geocode({'latLng': latlng}, function(results, status) {
      if (status == google.maps.GeocoderStatus.OK) {
            var level_1;
            var level_2;
            for (var x = 0, length_1 = results.length; x < length_1; x++){
              for (var y = 0, length_2 = results[x].address_components.length; y < length_2; y++){
                  var type = results[x].address_components[y].types[0];
                    if ( type === "administrative_area_level_1") {
                      level_1 = results[x].address_components[y].long_name;
                      if (level_2) break;
                    } else if (type === "locality"){
                      level_2 = results[x].address_components[y].long_name;
                      if (level_1) break;
                    }
                }
            }
            updateAddress(level_2, level_1);
       } 
  });
}

function updateAddress(city, prov){
   // do what you want with the address here
}

不要尝试返回结果,因为你会发现它们是未定义的——这是异步服务的结果。你必须调用一个函数,比如updateAddress();


你需要跳出每个循环,检查你的控制台,不过代码运行得非常好,非常感谢! - luke_mclachlan

5
我创建了这个函数来获取地理编码结果的主要信息:
const getDataFromGeoCoderResult = (geoCoderResponse) => {
  const geoCoderResponseHead = geoCoderResponse[0];
  const geoCoderData = geoCoderResponseHead.address_components;
  const isEmptyData = !geoCoderResponseHead || !geoCoderData;

  if (isEmptyData) return {};

  return geoCoderData.reduce((acc, { types, long_name: value }) => {
    const type = types[0];

    switch (type) {
      case 'route':
        return { ...acc, route: value };
      case 'locality':
        return { ...acc, locality: value };
      case 'country':
        return { ...acc, country: value };
      case 'postal_code_prefix':
        return { ...acc, postalCodePrefix: value };
      case 'street_number':
        return { ...acc, streetNumber: value };
      default:
        return acc;
    }
  }, {});
};

那么,您可以像这样使用它:

const geoCoderResponse = await geocodeByAddress(value);
const geoCoderData = getDataFromGeoCoderResult(geoCoderResponse);

假设你要搜索圣地亚哥伯纳乌球场,那么结果将是:

{
  country: 'Spain',
  locality: 'Madrid',
  route: 'Avenida de Concha Espina',
  streetNumber: '1',
}

4
这对我有帮助:

这对我有帮助:

const localityObject = body.results[0].address_components.filter((obj) => {
  return obj.types.includes('locality');
})[0];
const city = localityObject.long_name;

或者一次性完成:

const city = body.results[0].address_components.filter((obj) => {
  return obj.types.includes('locality');
)[0].long_name;

我正在使用Node进行操作,所以这样是可以的。如果你需要支持IE浏览器,你需要为 Array.prototype.includes 使用一个polyfill或寻找其他方法来实现。


3

我认为谷歌没有提供获取这些功能真是令人头疼。无论如何,我认为找到正确的对象的最佳方法是:

geocoder.geocode({'address': request.term }, function(results, status){

   response($.map(results, function(item){

      var city = $.grep(item.address_components, function(x){
         return $.inArray('locality', x.types) != -1;
      })[0].short_name;

      alert(city);
   }            
}); 

1
如果存在,返回所在地区。如果不存在,则返回administrative_area_1
city = results[0].address_components.filter(function(addr){
   return (addr.types[0]=='locality')?1:(addr.types[0]=='administrative_area_level_1')?1:0;
});

1
// Use Google Geocoder to get Lat/Lon for Address
function codeAddress() {
    // Function geocodes address1 in the Edit Panel and fills in lat and lon
    address = document.getElementById("tbAddress").value;
    geocoder.geocode({ 'address': address }, function (results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
            loc[0] = results[0].geometry.location.lat();
            loc[1] = results[0].geometry.location.lng();
            document.getElementById("tbLat").value = loc[0];
            document.getElementById("tbLon").value = loc[1];
            var arrAddress = results[0].address_components;
            for (ac = 0; ac < arrAddress.length; ac++) {
                if (arrAddress[ac].types[0] == "street_number") { document.getElementById("tbUnit").value = arrAddress[ac].long_name }
                if (arrAddress[ac].types[0] == "route") { document.getElementById("tbStreet").value = arrAddress[ac].short_name }
                if (arrAddress[ac].types[0] == "locality") { document.getElementById("tbCity").value = arrAddress[ac].long_name }
                if (arrAddress[ac].types[0] == "administrative_area_level_1") { document.getElementById("tbState").value = arrAddress[ac].short_name }
                if (arrAddress[ac].types[0] == "postal_code") { document.getElementById("tbZip").value = arrAddress[ac].long_name }
            }
            document.getElementById("tbAddress").value = results[0].formatted_address;
        }
        document.getElementById("pResult").innerHTML = 'GeoCode Status:' + status;
    })
}

0

这里是一些可以与lodash js库一起使用的代码:(只需将$scope.x替换为您自己的变量名称以存储值)

    _.findKey(vObj.address_components, function(component) {

            if (component.types[0] == 'street_number') {
                $scope.eventDetail.location.address = component.short_name
            }

            if (component.types[0] == 'route') {
                $scope.eventDetail.location.address = $scope.eventDetail.location.address + " " + component.short_name;
            }

            if (component.types[0] == 'locality') {
                $scope.eventDetail.location.city = component.long_name;
            }

            if (component.types[0] == 'neighborhood') {
                $scope.eventDetail.location.neighborhood = component.long_name;
            }

        });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接