Google Maps: ¿cómo obtener el país, estado / provincia / región, ciudad con un valor lat/long?


Necesito una lista de países, estados y ciudades basada en una colección de valores lat/long que tengo. Necesito almacenar esta información de una manera que se preserve la jerarquía y sin duplicados (por ejemplo, "USA" y "United States" y "United States of America" son el mismo país; solo quiero una instancia de este país en mi base de datos).

¿Es posible hacer esto con la API de Google Map?

Author: StackOverflowNewbie, 2010-10-25

9 answers

Lo que está buscando se llama geocodificación inversa. Google proporciona un servicio de geocodificación inversa del lado del servidor a través de la API de Geocodificación de Google, que debería poder usar para su proyecto.

Así es como se vería una respuesta a la siguiente solicitud:

Http://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&sensor=false

Respuesta:

{
  "status": "OK",
  "results": [ {
    "types": [ "street_address" ],
    "formatted_address": "275-291 Bedford Ave, Brooklyn, NY 11211, USA",
    "address_components": [ {
      "long_name": "275-291",
      "short_name": "275-291",
      "types": [ "street_number" ]
    }, {
      "long_name": "Bedford Ave",
      "short_name": "Bedford Ave",
      "types": [ "route" ]
    }, {
      "long_name": "New York",
      "short_name": "New York",
      "types": [ "locality", "political" ]
    }, {
      "long_name": "Brooklyn",
      "short_name": "Brooklyn",
      "types": [ "administrative_area_level_3", "political" ]
    }, {
      "long_name": "Kings",
      "short_name": "Kings",
      "types": [ "administrative_area_level_2", "political" ]
    }, {
      "long_name": "New York",
      "short_name": "NY",
      "types": [ "administrative_area_level_1", "political" ]
    }, {
      "long_name": "United States",
      "short_name": "US",
      "types": [ "country", "political" ]
    }, {
      "long_name": "11211",
      "short_name": "11211",
      "types": [ "postal_code" ]
    } ],
    "geometry": {
      "location": {
        "lat": 40.7142298,
        "lng": -73.9614669
      },
      "location_type": "RANGE_INTERPOLATED",
      "viewport": {
        "southwest": {
          "lat": 40.7110822,
          "lng": -73.9646145
        },
        "northeast": {
          "lat": 40.7173774,
          "lng": -73.9583193
        }
      }
    }
  },

  ... Additional results[] ...

También puede optar por recibir el respuesta en xml en lugar de json, simplemente sustituyendo json por xml en el URI de solicitud:

Http://maps.googleapis.com/maps/api/geocode/xml?latlng=40.714224,-73.961452&sensor=false

Por lo que sé, Google también devolverá el mismo nombre para componentes de dirección, especialmente para nombres de alto nivel como nombres de países y nombres de ciudades. Sin embargo, tenga en cuenta que si bien los resultados son muy precisos para la mayoría de las aplicaciones, todavía se puede encontrar el error ortográfico ocasional o resultado ambiguo.

 123
Author: Daniel Vassallo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-25 10:22:54

Aquí tienes una respuesta básica: Obtener el nombre de la ciudad usando geolocalización

Pero para lo que está buscando, lo recomendaría de esta manera.

Solo si también necesita administrative_area_level_1, para almacenar diferentes cosas para París, Texas, EE. UU. y París, Ile-de-France, Francia y proporcionar una reserva manual:

--

Hay un problema en la manera de Michal, en que toma el primer resultado, no uno en particular. Utiliza resultados [0]. La forma en que me parece conveniente (acabo de modificar su código) es tomar SOLO el resultado cuyo tipo es "localidad", que siempre está presente, incluso en una eventual reserva manual en caso de que el navegador no soporte geolocalización.

A su manera: los resultados obtenidos son diferentes de usar http://maps.googleapis.com/maps/api/geocode/json?address=bucharest&sensor=false de uso http://maps.googleapis.com/maps/api/geocode/json?latlng=44.42514, 26.10540 & sensor = false (búsqueda por nombre / búsqueda por lat&lng)

Esto manera: los mismos resultados obtenidos.

<!DOCTYPE html> 
<html> 
<head> 
<meta name="viewport" content="initial-scale=1.0, user-scalable=no"/> 
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/> 
<title>Reverse Geocoding</title> 

<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script> 
<script type="text/javascript"> 
  var geocoder;

  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(successFunction, errorFunction);
} 
//Get the latitude and the longitude;
function successFunction(position) {
    var lat = position.coords.latitude;
    var lng = position.coords.longitude;
    codeLatLng(lat, lng)
}

function errorFunction(){
    alert("Geocoder failed");
}

  function initialize() {
    geocoder = new google.maps.Geocoder();



  }

  function codeLatLng(lat, lng) {

    var latlng = new google.maps.LatLng(lat, lng);
    geocoder.geocode({'latLng': latlng}, function(results, status) {
      if (status == google.maps.GeocoderStatus.OK) {
      //console.log(results);
        if (results[1]) {
        var indice=0;
        for (var j=0; j<results.length; j++)
        {
            if (results[j].types[0]=='locality')
                {
                    indice=j;
                    break;
                }
            }
        alert('The good number is: '+j);
        console.log(results[j]);
        for (var i=0; i<results[j].address_components.length; i++)
            {
                if (results[j].address_components[i].types[0] == "locality") {
                        //this is the object you are looking for City
                        city = results[j].address_components[i];
                    }
                if (results[j].address_components[i].types[0] == "administrative_area_level_1") {
                        //this is the object you are looking for State
                        region = results[j].address_components[i];
                    }
                if (results[j].address_components[i].types[0] == "country") {
                        //this is the object you are looking for
                        country = results[j].address_components[i];
                    }
            }

            //city data
            alert(city.long_name + " || " + region.long_name + " || " + country.short_name)


            } else {
              alert("No results found");
            }
        //}
      } else {
        alert("Geocoder failed due to: " + status);
      }
    });
  }
</script> 
</head> 
<body onload="initialize()"> 

</body> 
</html> 
 18
Author: tabacitu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-16 10:29:49

Utilicé esta pregunta como punto de partida para mi propia solución. Pensé que era apropiado contribuir mi código de vuelta ya que es más pequeño que tabacitu

Dependencias:

Código:

if(geoPosition.init()){  

    var foundLocation = function(city, state, country, lat, lon){
        //do stuff with your location! any of the first 3 args may be null
        console.log(arguments);
    }

    var geocoder = new google.maps.Geocoder(); 
    geoPosition.getCurrentPosition(function(r){
        var findResult = function(results, name){
            var result =  _.find(results, function(obj){
                return obj.types[0] == name && obj.types[1] == "political";
            });
            return result ? result.short_name : null;
        };
        geocoder.geocode({'latLng': new google.maps.LatLng(r.coords.latitude, r.coords.longitude)}, function(results, status) {
            if (status == google.maps.GeocoderStatus.OK && results.length) {
                results = results[0].address_components;
                var city = findResult(results, "locality");
                var state = findResult(results, "administrative_area_level_1");
                var country = findResult(results, "country");
                foundLocation(city, state, country, r.coords.latitude, r.coords.longitude);
            } else {
                foundLocation(null, null, null, r.coords.latitude, r.coords.longitude);
            }
        });
    }, { enableHighAccuracy:false, maximumAge: 1000 * 60 * 1 });
}
 4
Author: mkoryak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-06 05:31:29

Encontré el GeoCoder javascript un poco defectuoso cuando lo incluí en mis archivos jsp.

También puedes probar esto:



    var lat = "43.7667855" ;
    var long = "-79.2157321" ;
    var url = "https://maps.googleapis.com/maps/api/geocode/json?latlng="
       +lat+","+long+"&sensor=false";
    $.get(url).success(function(data) {
       var loc1 = data.results[0];
       var county, city;
         $.each(loc1, function(k1,v1) {
            if (k1 == "address_components") {
               for (var i = 0; i < v1.length; i++) {
                  for (k2 in v1[i]) {
                     if (k2 == "types") {
                        var types = v1[i][k2];
                        if (types[0] =="sublocality_level_1") {
                            county = v1[i].long_name;
                            //alert ("county: " + county);
                        } 
                        if (types[0] =="locality") {
                           city = v1[i].long_name;
                           //alert ("city: " + city);
                       } 
                     }

                  }          

               }

            }

         });
         $('#city').html(city); 
    }); 

 3
Author: YP Leung,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-12 14:41:28

Escribí esta función que extrae lo que está buscando basado en el address_components devuelto desde la API de gmaps. Esta es la ciudad (por ejemplo).

export const getAddressCity = (address, length) => {
  const findType = type => type.types[0] === "locality"
  const location = address.map(obj => obj)
  const rr = location.filter(findType)[0]

  return (
    length === 'short'
      ? rr.short_name
      : rr.long_name
  )
}

Cambie locality a administrative_area_level_1 para el Estado, etc.

En mi código js estoy usando así:

const location =`${getAddressCity(address_components, 'short')}, ${getAddressState(address_components, 'short')}`

Volverá: Waltham, MA

 2
Author: sburke0708,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-17 04:42:16

Solo prueba este código este código trabaja conmigo

var posOptions = {timeout: 10000, enableHighAccuracy: false};
$cordovaGeolocation.getCurrentPosition(posOptions).then(function (position) {
var lat = position.coords.latitude;
var long = position.coords.longitude;
 //console.log(lat +"          "+long);
$http.get('https://maps.googleapis.com/maps/api/geocode/json?latlng=' + lat + ',' + long + '&key=your key here').success(function (output) {
//console.log( JSON.stringify(output.results[0]));
//console.log( JSON.stringify(output.results[0].address_components[4].short_name));
var results = output.results;
if (results[0]) {
//console.log("results.length= "+results.length);
//console.log("hi "+JSON.stringify(results[0],null,4));
for (var j = 0; j < results.length; j++){
 //console.log("j= "+j);
//console.log(JSON.stringify(results[j],null,4));
for (var i = 0; i < results[j].address_components.length; i++){
 if(results[j].address_components[i].types[0] == "country") {
 //this is the object you are looking for
  country = results[j].address_components[i];
 }
 }
 }
 console.log(country.long_name);
 console.log(country.short_name);
 } else {
 alert("No results found");
 console.log("No results found");
 }
 });
 }, function (err) {
 });
 0
Author: HMahmoud,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-07 13:45:01

He creado una pequeña función mapeador:

private getAddressParts(object): Object {
    let address = {};
    const address_components = object.address_components;
    address_components.forEach(element => {
        address[element.types[0]] = element.short_name;
    });
    return address;
}

Es una solución para Angular 4 pero creo que entenderás la idea.

Uso:

geocoder.geocode({ 'location' : latlng }, (results, status) => {
    if (status === google.maps.GeocoderStatus.OK) {
        const address = {
            formatted_address: results[0].formatted_address,
            address_parts: this.getAddressParts(results[0])
        };
        (....)
    }

De esta manera el objeto address será algo así:

address: {
    address_parts: {
        administrative_area_level_1: "NY",
        administrative_area_level_2: "New York County",
        country: "US",
        locality: "New York",
        neighborhood: "Lower Manhattan",
        political: "Manhattan",
        postal_code: "10038",
        route: "Beekman St",
        street_number: "90",
    },
    formatted_address: "90 Beekman St, New York, NY 10038, USA"
}

Espero que ayude!

 0
Author: Szkíta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-10 11:25:09
 <div id="location"></div>
        <script>
            window.onload = function () {
                var startPos;
                var geoOptions = {
                    maximumAge: 5 * 60 * 1000,
                    timeout: 10 * 1000,
                    enableHighAccuracy: true
                }


                var geoSuccess = function (position) {
                    startPos = position;
                    geocodeLatLng(startPos.coords.latitude, startPos.coords.longitude);

                };
                var geoError = function (error) {
                    console.log('Error occurred. Error code: ' + error.code);
                    // error.code can be:
                    //   0: unknown error
                    //   1: permission denied
                    //   2: position unavailable (error response from location provider)
                    //   3: timed out
                };

                navigator.geolocation.getCurrentPosition(geoSuccess, geoError, geoOptions);
            };
            function geocodeLatLng(lat, lng) {
                var geocoder = new google.maps.Geocoder;
                var latlng = {lat: parseFloat(lat), lng: parseFloat(lng)};
                geocoder.geocode({'location': latlng}, function (results, status) {
                    if (status === 'OK') {
                        console.log(results)
                        if (results[0]) {
                            document.getElementById('location').innerHTML = results[0].formatted_address;
                            var street = "";
                            var city = "";
                            var state = "";
                            var country = "";
                            var zipcode = "";
                            for (var i = 0; i < results.length; i++) {
                                if (results[i].types[0] === "locality") {
                                    city = results[i].address_components[0].long_name;
                                    state = results[i].address_components[2].long_name;

                                }
                                if (results[i].types[0] === "postal_code" && zipcode == "") {
                                    zipcode = results[i].address_components[0].long_name;

                                }
                                if (results[i].types[0] === "country") {
                                    country = results[i].address_components[0].long_name;

                                }
                                if (results[i].types[0] === "route" && street == "") {

                                    for (var j = 0; j < 4; j++) {
                                        if (j == 0) {
                                            street = results[i].address_components[j].long_name;
                                        } else {
                                            street += ", " + results[i].address_components[j].long_name;
                                        }
                                    }

                                }
                                if (results[i].types[0] === "street_address") {
                                    for (var j = 0; j < 4; j++) {
                                        if (j == 0) {
                                            street = results[i].address_components[j].long_name;
                                        } else {
                                            street += ", " + results[i].address_components[j].long_name;
                                        }
                                    }

                                }
                            }
                            if (zipcode == "") {
                                if (typeof results[0].address_components[8] !== 'undefined') {
                                    zipcode = results[0].address_components[8].long_name;
                                }
                            }
                            if (country == "") {
                                if (typeof results[0].address_components[7] !== 'undefined') {
                                    country = results[0].address_components[7].long_name;
                                }
                            }
                            if (state == "") {
                                if (typeof results[0].address_components[6] !== 'undefined') {
                                    state = results[0].address_components[6].long_name;
                                }
                            }
                            if (city == "") {
                                if (typeof results[0].address_components[5] !== 'undefined') {
                                    city = results[0].address_components[5].long_name;
                                }
                            }

                            var address = {
                                "street": street,
                                "city": city,
                                "state": state,
                                "country": country,
                                "zipcode": zipcode,
                            };

                            document.getElementById('location').innerHTML = document.getElementById('location').innerHTML + "<br/>Street : " + address.street + "<br/>City : " + address.city + "<br/>State : " + address.state + "<br/>Country : " + address.country + "<br/>zipcode : " + address.zipcode;
                            console.log(address);
                        } else {
                            window.alert('No results found');
                        }
                    } else {
                        window.alert('Geocoder failed due to: ' + status);
                    }
                });
            }
        </script>

        <script async defer
                src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY">
        </script>
 0
Author: Deepak Kr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-15 08:37:07

@Szkíta Tenía una gran solución al crear una función que obtiene las partes de la dirección en una matriz con nombre. Aquí hay una solución compilada para aquellos que desean usar JavaScript simple.

Función para convertir los resultados a la matriz nombrada:

function getAddressParts(obj) {

    var address = [];

    obj.address_components.forEach( function(el) {
        address[el.types[0]] = el.short_name;
    });

    return address;

} //getAddressParts()

Geocodificar los valores LAT / LNG:

geocoder.geocode( { 'location' : latlng }, function(results, status) {

    if (status == google.maps.GeocoderStatus.OK) {
        var addressParts =  getAddressParts(results[0]);

        // the city
        var city = addressParts.locality;

        // the state
        var state = addressParts.administrative_area_level_1;
    }

});
 0
Author: mbacon40,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-29 16:44:09