Google Maps: как получить страну, штат/провинцию/регион, город с учетом значения lat/long?
Мне нужен список стран, Штатов и городов, основанный на коллекции значений lat/long, которые у меня есть. Мне нужно хранить эту информацию таким образом, чтобы иерархия сохранялась и не дублировалась (например, "США" и "Соединенные Штаты" и "Соединенные Штаты Америки" - это одна и та же страна; я хочу только один экземпляр этой страны в своей базе данных).
возможно ли это сделать с Google Map API?
9 ответов:
то, что вы ищете называется обратное геокодирование. Google предоставляет услугу обратного геокодирования на стороне сервера через Google Geocoding API, который вы сможете использовать для вашего проекта.
вот как будет выглядеть ответ на следующий запрос:
http://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&sensor=false
ответ:
{ "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[] ...
вы также можете выбрать получение ответа в xml вместо json, просто подставив json для xml в URI запроса:
http://maps.googleapis.com/maps/api/geocode/xml?latlng=40.714224,-73.961452&sensor=false
насколько я знаю, Google также будет возвращает то же имя для компонентов адреса, особенно для имен высокого уровня, таких как названия стран и городов. Тем не менее, имейте в виду, что хотя результаты очень точны для большинства приложений, вы все равно можете найти случайную орфографическую ошибку или неоднозначный результат.
у вас есть основной ответ здесь: получить название города с помощью геолокации
но для того, что вы ищете, я бы рекомендовал этот способ.
только если вам также нужен administrative_area_level_1, чтобы хранить разные вещи для Парижа, Техаса, США и Парижа, Иль-де-Франс, Франция и предоставить ручной резерв:
--
есть проблема в пути Михала, в том, что он принимает первый результат, а не конкретный. Он использует результаты[0]. Путь Я считаю нужным (я только что изменил его код) взять только результат, тип которого "локальность", который всегда присутствует, даже в конечном ручном резервном варианте, если браузер не поддерживает геолокацию.
пути: полученные результаты отличаются от использования http://maps.googleapis.com/maps/api/geocode/json?address=bucharest&sensor=false чем от использования http://maps.googleapis.com/maps/api/geocode/json?latlng=44.42514,26.10540&sensor=false (поиск по имя / поиск по lat & lng)
таким образом: те же полученные результаты.
<!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>
я использовал этот вопрос в качестве отправной точки для собственного решения. Подумал, что было бы целесообразно внести свой код обратно, так как его меньше, чем tabacitu
зависимости:
код:
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 }); }
Я нашел геокодер javascript немного багги, когда я включил его в Мои файлы jsp.
вы также можете попробовать это:
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); });
Я написал функцию, которая извлекает то, что вы ищете на основании
address_components
возвращено из API gmaps. Это город (например).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 ) }
изменить
locality
доadministrative_area_level_1
для государства и т. д.в моем JS-коде я использую так:
const location =`${getAddressCity(address_components, 'short')}, ${getAddressState(address_components, 'short')}`
вернутся:
Waltham, MA
просто попробуйте этот код этот код работает со мной
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) { });
Я создал небольшую функцию mapper:
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; }
это решение для углового 4, но я думаю, что вы получите идею.
использование:
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]) }; (....) }
таким образом
address
объект будет выглядеть примерно так: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" }
надеюсь, что это помогает!
<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>
@Szkíta было отличное решение, создав функцию, которая получает адресные части в именованном массиве. Вот скомпилированный решение для тех, кто хочет использовать простой JavaScript.
функция для преобразования результатов в именованный массив:
function getAddressParts(obj) { var address = []; obj.address_components.forEach( function(el) { address[el.types[0]] = el.short_name; }); return address; } //getAddressParts()
Геокодируйте значения 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; } });