Obtener el nombre de la ciudad usando geolocalización

140

Logré obtener la latitud y longitud del usuario utilizando la geolocalización basada en HTML.

//Check if browser supports W3C Geolocation API
if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(successFunction, errorFunction);
} 
//Get latitude and longitude;
function successFunction(position) {
    var lat = position.coords.latitude;
    var long = position.coords.longitude;
}

Quiero mostrar el nombre de la ciudad, parece que la única forma de obtenerlo es usar una API de geolocalización inversa. Leí la documentación de Google para la geolocalización inversa, pero no sé cómo obtener la salida en mi sitio.

No sé cómo usar esto: "http://maps.googleapis.com/maps/api/geocode/json?latlng='+lat+','+long+'&sensor=true"para mostrar el nombre de la ciudad en la página.

¿Cómo puedo conseguir esto?

lisovaccaro
fuente
44
Si no vas a usar mapas, SABES que esto va en contra de los TOS de Google, ¿verdad? Punto 10.4 aquí developers.google.com/maps/terms No se puede usar el Contenido sin un mapa de Google. A menos que la documentación de las API de Maps lo permita expresamente, no utilizará el contenido en una implementación de API de Maps sin un mapa de Google correspondiente. Por ejemplo, puede mostrar imágenes de Street View sin un mapa de Google correspondiente porque la documentación de las API de Maps permite expresamente este uso.
PirateApp
55
Sí, @PirateApp tiene un buen punto. Puede haber mejores servicios por ahí. He trabajado con SmartyStreets antes y sé que tienen términos de servicio mucho más abiertos. Sin embargo, la mayoría de los servicios no hacen geocodificación inversa. Sé que Texas A&M tiene un servicio gratuito, pero tienen advertencias de TOS de que no puede recopilar datos sobre otras personas, y han tenido problemas de tiempo de actividad y precisión antes.
Joseph Hansen

Respuestas:

201

Harías algo así usando la API de Google.

Tenga en cuenta que debe incluir la biblioteca de Google Maps para que esto funcione. Google geocoder devuelve una gran cantidad de componentes de dirección, por lo que debe hacer una suposición informada sobre cuál tendrá la ciudad.

"Administrative_area_level_1" suele ser lo que está buscando, pero a veces la localidad es la ciudad que busca.

De todos modos, más detalles sobre los tipos de respuesta de Google se pueden encontrar aquí y aquí .

A continuación se muestra el código que debería hacer el truco:

<!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]) {
         //formatted address
         alert(results[0].formatted_address)
        //find country name
             for (var i=0; i<results[0].address_components.length; i++) {
            for (var b=0;b<results[0].address_components[i].types.length;b++) {

            //there are different types that might hold a city admin_area_lvl_1 usually does in come cases looking for sublocality type will be more appropriate
                if (results[0].address_components[i].types[b] == "administrative_area_level_1") {
                    //this is the object you are looking for
                    city= results[0].address_components[i];
                    break;
                }
            }
        }
        //city data
        alert(city.short_name + " " + city.long_name)


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

</body> 
</html> 
Michal
fuente
3
No es cierto para el nivel 1 del área de administración, a veces el nombre de la ciudad no está allí. - {"long_name" => "San Francisco", "types" => ["Administrative_area_level_2", "político"], "nombre_corto" => "San Francisco"}, {"long_name" => "California", "tipos "=> [" Administrative_area_level_1 "," político "]," nombre_corto "=>" CA "}, {" nombre_ largo "=>" Estados Unidos "," tipos "=> [" país "," político "]," short_name "=>" US "}
Ming Tsai
55
Para V3, la cadena {'latlng': latlng} debe cambiarse a 'ubicación', como en ... geocode ({'ubicación': latlng}). Este ejemplo me llevó casi allí, pero la cadena 'latlng' ya no parece ser válida en las nuevas API. Consulte: developers.google.com/maps/documentation/javascript/… para obtener información específica.
binarygiant
@Michal, ¿cómo podemos encontrar solo el nombre o el código del país en lugar de la dirección completa?
ajay
1
@ajay en la prueba de instrucción if para "país" y la variable de ciudad ahora devolverá los datos del país. Si cambia el nombre a country = results [0] .address_components [i] puede acceder a los datos por country.long_name y country.short_name
Michal
¿Hay alguna manera de limitar esto a las ciudades dentro de una provincia o simplemente para verificar si la ubicación es de una provincia específica y si el usuario es redirigido a una página web específica?
siento,
52

Otro enfoque para esto es utilizar mi servicio, http://ipinfo.io , que devuelve el nombre de la ciudad, la región y el país en función de la dirección IP actual del usuario. Aquí hay un ejemplo simple:

$.get("http://ipinfo.io", function(response) {
    console.log(response.city, response.country);
}, "jsonp");

Aquí hay un ejemplo más detallado de JSFiddle que también imprime la información de respuesta completa, para que pueda ver todos los detalles disponibles: http://jsfiddle.net/zK5FN/2/

Ben Dowling
fuente
23
Aunque no es tan preciso.
Salman von Abbas
44
No se pudo detectar la ciudad e incluso el trgion de IP de un gran proveedor ruso: (
Jehy
2
Lol ... esto le da a mi red interna ip (192.168 ...)
major-mann
¿Puedo hacerlo desde un navegador de dispositivo (portátil)?
Arti
No parece confiable. Estoy usando una computadora portátil y un teléfono móvil en este momento. ¡Las ciudades que se muestran en ambos dispositivos a través de ipinfo.io están a 530 kilómetros de distancia!
Ashish Goyal
52

$.ajax({
  url: "https://geolocation-db.com/jsonp",
  jsonpCallback: "callback",
  dataType: "jsonp",
  success: function(location) {
    $('#country').html(location.country_name);
    $('#state').html(location.state);
    $('#city').html(location.city);
    $('#latitude').html(location.latitude);
    $('#longitude').html(location.longitude);
    $('#ip').html(location.IPv4);
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

<div>Country: <span id="country"></span></div>
  <div>State: <span id="state"></span></div>
    <div>City: <span id="city"></span></div>
      <div>Latitude: <span id="latitude"></span></div>
        <div>Longitude: <span id="longitude"></span></div>
          <div>IP: <span id="ip"></span></div>

El uso de la geolocalización html5 requiere permiso del usuario. En caso de que no desee esto, busque un localizador externo como https://geolocation-db.com IPv6 es compatible. No se permiten restricciones ni solicitudes ilimitadas.

Ejemplo

Para un ejemplo puro de JavaScript, sin usar jQuery, consulte esta respuesta.

Kurt Van den Branden
fuente
17

Puede obtener el nombre de la ciudad, el país, el nombre de la calle y otros datos geográficos utilizando la API de geocodificación de Google Maps

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script type="text/javascript" src="https://code.jquery.com/jquery-2.2.3.js"></script>
</head>
<body>
    <script type="text/javascript">
        navigator.geolocation.getCurrentPosition(success, error);

        function success(position) {
            console.log(position.coords.latitude)
            console.log(position.coords.longitude)

            var GEOCODING = 'https://maps.googleapis.com/maps/api/geocode/json?latlng=' + position.coords.latitude + '%2C' + position.coords.longitude + '&language=en';

            $.getJSON(GEOCODING).done(function(location) {
                console.log(location)
            })

        }

        function error(err) {
            console.log(err)
        }
    </script>
</body>
</html>

y para mostrar estos datos en la página usando jQuery

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script type="text/javascript" src="https://code.jquery.com/jquery-2.2.3.js"></script>
</head>
<body>

    <p>Country: <span id="country"></span></p>
    <p>State: <span id="state"></span></p>
    <p>City: <span id="city"></span></p>
    <p>Address: <span id="address"></span></p>

    <p>Latitude: <span id="latitude"></span></p>
    <p>Longitude: <span id="longitude"></span></p>

    <script type="text/javascript">
        navigator.geolocation.getCurrentPosition(success, error);

        function success(position) {

            var GEOCODING = 'https://maps.googleapis.com/maps/api/geocode/json?latlng=' + position.coords.latitude + '%2C' + position.coords.longitude + '&language=en';

            $.getJSON(GEOCODING).done(function(location) {
                $('#country').html(location.results[0].address_components[5].long_name);
                $('#state').html(location.results[0].address_components[4].long_name);
                $('#city').html(location.results[0].address_components[2].long_name);
                $('#address').html(location.results[0].formatted_address);
                $('#latitude').html(position.coords.latitude);
                $('#longitude').html(position.coords.longitude);
            })

        }

        function error(err) {
            console.log(err)
        }
    </script>
</body>
</html>
Mikhail
fuente
15

Aquí hay una versión de trabajo actualizada para mí que obtendrá City / Town. Parece que algunos campos están modificados en la respuesta json. Refiriendo respuestas anteriores para estas preguntas. (Gracias a Michal y una referencia más: Enlace

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) {
      if (results[1]) {
        var arrAddress = results;
        console.log(results);
        $.each(arrAddress, function(i, address_component) {
          if (address_component.types[0] == "locality") {
            console.log("City: " + address_component.address_components[0].long_name);
            itemLocality = address_component.address_components[0].long_name;
          }
        });
      } else {
        alert("No results found");
      }
    } else {
      alert("Geocoder failed due to: " + status);
    }
  });
}
Pradeep
fuente
10

geolocator.js puede hacer eso. (Soy el autor)

Cómo obtener el nombre de la ciudad (dirección limitada)

geolocator.locateByIP(options, function (err, location) {
    console.log(location.address.city);
});

Obteniendo información completa de la dirección

El siguiente ejemplo probará primero la API de geolocalización HTML5 para obtener las coordenadas exactas. Si falla o se rechaza, recurrirá a la búsqueda de Geo-IP. Una vez que obtenga las coordenadas, geocodificará las coordenadas en una dirección.

var options = {
    enableHighAccuracy: true,
    fallbackToIP: true, // fallback to IP if Geolocation fails or rejected
    addressLookup: true
};
geolocator.locate(options, function (err, location) {
    console.log(location.address.city);
});

Esto utiliza las API de Google internamente (para la búsqueda de direcciones). Entonces, antes de esta llamada, debe configurar el geolocalizador con su clave API de Google.

geolocator.config({
    language: "en",
    google: {
        version: "3",
        key: "YOUR-GOOGLE-API-KEY"
    }
});

Geolocator admite ubicación geográfica (a través de búsquedas HTML5 o IP), geocodificación, búsquedas de direcciones (geocodificación inversa), distancia y duraciones, información de zona horaria y muchas más funciones ...

Onur Yıldırım
fuente
6

Después de buscar y reconstruir un par de soluciones diferentes junto con mis propias cosas, se me ocurrió esta función:

function parse_place(place)
{
    var location = [];

    for (var ac = 0; ac < place.address_components.length; ac++)
    {
        var component = place.address_components[ac];

        switch(component.types[0])
        {
            case 'locality':
                location['city'] = component.long_name;
                break;
            case 'administrative_area_level_1':
                location['state'] = component.long_name;
                break;
            case 'country':
                location['country'] = component.long_name;
                break;
        }
    };

    return location;
}
Jafo
fuente
3

Puedes usar https://ip-api.io/ para obtener el nombre de la ciudad. Es compatible con IPv6.

Como beneficio adicional, permite verificar si la dirección IP es un nodo tor, proxy público o spammer.

Código Javascript:

$(document).ready(function () {
        $('#btnGetIpDetail').click(function () {
            if ($('#txtIP').val() == '') {
                alert('IP address is reqired');
                return false;
            }
            $.getJSON("http://ip-api.io/json/" + $('#txtIP').val(),
                 function (result) {
                     alert('City Name: ' + result.city)
                     console.log(result);
                 });
        });
    });

código HTML

<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<div>
    <input type="text" id="txtIP" />
    <button id="btnGetIpDetail">Get Location of IP</button>
</div>

Salida JSON

{
    "ip": "64.30.228.118",
    "country_code": "US",
    "country_name": "United States",
    "region_code": "FL",
    "region_name": "Florida",
    "city": "Fort Lauderdale",
    "zip_code": "33309",
    "time_zone": "America/New_York",
    "latitude": 26.1882,
    "longitude": -80.1711,
    "metro_code": 528,
    "suspicious_factors": {
        "is_proxy": false,
        "is_tor_node": false,
        "is_spam": false,
        "is_suspicious": false
    }
}
Vindhyachal Kumar
fuente
2

Como @PirateApp mencionó en su comentario, está explícitamente en contra de las licencias de API de Google Maps utilizar la API de Google Maps como lo desee.

Tiene varias alternativas, incluida la descarga de una base de datos Geoip y la consulta local o el uso de un servicio API de terceros, como mi servicio ipdata.co .

ipdata le brinda la ubicación geográfica, la organización, la moneda, la zona horaria, el código de llamada, la bandera y los datos de estado del nodo de salida Tor desde cualquier dirección IPv4 o IPv6.

¡Y es escalable con 10 puntos finales globales, cada uno capaz de manejar> 10,000 solicitudes por segundo!

Esta respuesta utiliza una clave API 'prueba' que es muy limitada y solo está destinada a probar algunas llamadas. Regístrese para obtener su propia clave API gratuita y obtenga hasta 1500 solicitudes diarias de desarrollo.

$.get("https://api.ipdata.co?api-key=test", function(response) {
  $("#ip").html("IP: " + response.ip);
  $("#city").html(response.city + ", " + response.region);
  $("#response").html(JSON.stringify(response, null, 4));
}, "jsonp");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1><a href="https://ipdata.co">ipdata.co</a> - IP geolocation API</h1>

<div id="ip"></div>
<div id="city"></div>
<pre id="response"></pre>

El violín; https://jsfiddle.net/ipdata/6wtf0q4g/922/

Jonathan
fuente
1

Aquí hay otra oportunidad ... Agregar más a la respuesta aceptada posiblemente más completa ... por supuesto, switch -case hará que parezca elegante.

function parseGeoLocationResults(result) {
    const parsedResult = {}
    const {address_components} = result;

    for (var i = 0; i < address_components.length; i++) {
        for (var b = 0; b < address_components[i].types.length; b++) {
            if (address_components[i].types[b] == "street_number") {
                //this is the object you are looking for
                parsedResult.street_number = address_components[i].long_name;
                break;
            }
            else if (address_components[i].types[b] == "route") {
                //this is the object you are looking for
                parsedResult.street_name = address_components[i].long_name;
                break;
            }
            else if (address_components[i].types[b] == "sublocality_level_1") {
                //this is the object you are looking for
                parsedResult.sublocality_level_1 = address_components[i].long_name;
                break;
            }
            else if (address_components[i].types[b] == "sublocality_level_2") {
                //this is the object you are looking for
                parsedResult.sublocality_level_2 = address_components[i].long_name;
                break;
            }
            else if (address_components[i].types[b] == "sublocality_level_3") {
                //this is the object you are looking for
                parsedResult.sublocality_level_3 = address_components[i].long_name;
                break;
            }
            else if (address_components[i].types[b] == "neighborhood") {
                //this is the object you are looking for
                parsedResult.neighborhood = address_components[i].long_name;
                break;
            }
            else if (address_components[i].types[b] == "locality") {
                //this is the object you are looking for
                parsedResult.city = address_components[i].long_name;
                break;
            }
            else if (address_components[i].types[b] == "administrative_area_level_1") {
                //this is the object you are looking for
                parsedResult.state = address_components[i].long_name;
                break;
            }

            else if (address_components[i].types[b] == "postal_code") {
                //this is the object you are looking for
                parsedResult.zip = address_components[i].long_name;
                break;
            }
            else if (address_components[i].types[b] == "country") {
                //this is the object you are looking for
                parsedResult.country = address_components[i].long_name;
                break;
            }
        }
    }
    return parsedResult;
}
usuario3124360
fuente
0

Aquí hay una función fácil que puede usar para obtenerla. Solía axios para hacer la solicitud de la API, pero se puede usar cualquier otra cosa.

async function getCountry(lat, long) {
  const { data: { results } } = await axios.get(`https://maps.googleapis.com/maps/api/geocode/json?latlng=${lat},${long}&key=${GOOGLE_API_KEY}`);
  const { address_components } = results[0];

  for (let i = 0; i < address_components.length; i++) {
    const { types, long_name } = address_components[i];

    if (types.indexOf("country") !== -1) return long_name;
  }
}
Kingsley Kbc Comics
fuente