我正在尝试使用Google地图javascript API建立一个网站,以查找城市周围的酒店,并比较每个酒店与用户输入位置之间的距离,以便找到离他们想要访问的所有地点最近的酒店
首先,它计算用户输入位置的坐标(使用地理编码API工作正常),然后获取酒店的坐标/谷歌位置信息。
使用google.maps.geometry.spherical.computeDistanceBetween(LatLng a,LatLng b);为了获得每个酒店和用户输入的地址之间的距离,该函数返回此错误:
未捕获的TypeError:无法读取未定义的属性'lat'
但是,我传递给函数的两个LatLng参数似乎都不是null或未定义。
每个if(location1!=“”),if(location2!=“”)等代码块检查酒店或位置的LatLng对象是否为空,如果是,则打印错误,但是当我运行网页时,这些错误不打印在javascript控制台中。
以下是相关的Javascript和HTML:
var map;
var infowindow;
function initMap() {
var pyrmont = {lat: -33.867, lng: 151.195};
map = new google.maps.Map(document.getElementById('map'), {
center: pyrmont,
zoom: 15
});
infowindow = new google.maps.InfoWindow();
}
function createMarker(place) {
var placeLoc = place.geometry.location;
var marker = new google.maps.Marker({
map: map,
position: place.geometry.location
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(place.name);
infowindow.open(map, this);
});
}
var nearbyHotels = [];
var cityCoordinates;
var cityCoordinatesLatLng;
function findHotels()
{
var nearbyHotelsLat = [];
var nearbyHotelsLong = [];
var locationScores1 = [];
var locationScores2 = [];
var locationScores3 = [];
var locationScores4 = [];
var locationScores5 = [];
var avgScores = [];
var geocoder = new google.maps.Geocoder();
var cityAddress = document.getElementById('locations_cityField').value;
var radiusSearch = parseInt(document.getElementById('locations_rangeField').value);
var location1 = document.getElementById('locations_location1').value;
var location2 = document.getElementById('locations_location2').value;
var location3 = document.getElementById('locations_location3').value;
var location4 = document.getElementById('locations_location4').value;
var location5 = document.getElementById('locations_location5').value;
var location1LatLng;
var location2LatLng;
var location3LatLng;
var location4LatLng;
var location5LatLng;
if(location1 != "" && location1 != undefined)
location1LatLng = geocodeAddress(geocoder, location1);
if(location2 != "" && location2 != undefined)
location2LatLng = geocodeAddress(geocoder, location2);
if(location3 != "" && location3 != undefined)
location3LatLng = geocodeAddress(geocoder, location3);
if(location4 != "" && location4 != undefined)
location4LatLng = geocodeAddress(geocoder, location4);
if(location5 != "" && location5 != undefined)
location5LatLng = geocodeAddress(geocoder, location5);
console.log(location1LatLng);
var cityLoc = geocodeAddress(geocoder, cityAddress);
setTimeout(function(){
var coordSplit = cityCoordinates.split(",");
var lati = parseFloat(coordSplit[0]);
var lngi = parseFloat(coordSplit[1]);
var city = {lat: lati, lng: lngi};
var service = new google.maps.places.PlacesService(map);
service.nearbySearch({
location: city,
radius: radiusSearch,
types: ['lodging']
}, callback);
map.setCenter(cityLoc);
setTimeout(function(){
console.log("nearbyHotels.length: " + nearbyHotels.length);
if(location1 != "")
{
for(var i = 0; i < nearbyHotels.length; i++)
{
var hotelLatLng = nearbyHotels[i].geometry.location;
if(location1LatLng == "")
{
console.log("NULL LOCATION1LATLNG");
}
if(hotelLatLng == "")
{
console.log("NULL (1) HOTELLATLNG");
}
var dist = google.maps.geometry.spherical.computeDistanceBetween(location1LatLng, hotelLatLng);
locationScores1.push(dist);
}
}
if(location2 != "")
{
for(var i = 0; i < nearbyHotels.length; i++)
{
var hotelLatLng = nearbyHotels[i].geometry.location;
if(location2LatLng == "")
{
console.log("NULL LOCATION2LATLNG");
}
if(hotelLatLng == "")
{
console.log("NULL (2) HOTELLATLNG");
}
var dist = google.maps.geometry.spherical.computeDistanceBetween(location2LatLng, hotelLatLng);
locationScores2.push(dist);
}
}
if(location3 != "")
{
for(var i = 0; i < nearbyHotels.length; i++)
{
var hotelLatLng = nearbyHotels[i].geometry.location;
if(location3LatLng == "")
{
console.log("NULL LOCATION3LATLNG");
}
if(hotelLatLng == "")
{
console.log("NULL (3) HOTELLATLNG");
}
var dist = google.maps.geometry.spherical.computeDistanceBetween(location3LatLng, hotelLatLng);
locationScores3.push(dist);
}
}
if(location4 != "")
{
for(var i = 0; i < nearbyHotels.length; i++)
{
var hotelLatLng = nearbyHotels[i].geometry.location;
if(location4LatLng == "")
{
console.log("NULL LOCATION4LATLNG");
}
if(hotelLatLng == "")
{
console.log("NULL (4) HOTELLATLNG");
}
var dist = google.maps.geometry.spherical.computeDistanceBetween(location4LatLng, hotelLatLng);
locationScores4.push(dist);
}
}
if(location5 != "")
{
for(var i = 0; i < nearbyHotels.length; i++)
{
var hotelLatLng = nearbyHotels[i].geometry.location;
if(location5LatLng == "")
{
console.log("NULL LOCATION5LATLNG");
}
if(hotelLatLng == "")
{
console.log("NULL (5) HOTELLATLNG");
}
var dist = google.maps.geometry.spherical.computeDistanceBetween(location5LatLng, hotelLatLng);
locationScores5.push(dist);
}
}
for(var i = 0; i < nearbyHotels.length; i++)
{
var avgDist;
var numLocations = 0;
if(location1 != "")
{
numLocations++;
avgDist += locationScores1[i];
}
if(location2 != "")
{
numLocations++;
avgDist += locationScores2[i];
}
if(location3 != "")
{
numLocations++;
avgDist += locationScores3[i];
}
if(location4 != "")
{
numLocations++;
avgDist += locationScores4[i];
}
if(location5 != "")
{
numLocations++;
avgDist += locationScores5[i];
}
avgDist = avgDist / numLocations;
avgScores.push(avgDist);
}
var avgScoresSorted = avgScores.sort(function (a, b) {
return b - a;
});
for(var i = 0; i < avgScoresSorted.length; i++)
{
var index = avgScores.indexOf(avgScoresSorted[i]);
var hotelName = nearbyHotels[index].name;
var hotelAddress = nearbyHotels[index].vicinity;
document.getElementById("displayHotelsDiv").innerHTML += (i + 1) + ": " + hotelName + " (" + hotelAddress + ") - LocationScore: " + avgScoresSorted[i];
}
}, 10000);
}, 5000);
}
function callback(results, status) {
if (status === google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
console.log(results[i]);
createMarker(results[i]);
nearbyHotels.push(results[i]);
}
}
}
function initSearchButtonListener()
{
document.getElementById('button_searchhotels').addEventListener('click', function() {
findHotels();
});
initMap();
}
function geocodeAddress(geocoder, address) {
console.log("address " + address);
console.log("geocoder " + geocoder);
geocoder.geocode({'address': address}, function(results, status) {
if (status === google.maps.GeocoderStatus.OK) {
var coords = results[0].geometry.location.toString();
console.log("CoordsRaw: " + coords)
var coordsNoFirst = coords.substring(1);
var coordsNoLast = coordsNoFirst.slice(0, -1);
cityCoordinates = coordsNoLast;
console.log(cityCoordinates);
return results[0].geometry.location;
} else {
alert('Could not convert an address to latitude/longitude for the google maps API: ' + status);
}
});
}
与之相关的HTML:
<div class="container" id="locations">
<div class="row">
<div class="col-md-6">
<input type="text" class="form-control" id="locations_location1" placeholder="Enter address of the 1st location">
</div>
<div class="col-md-6">
<input type="text" class="form-control" id="locations_location2" placeholder="Enter address of the 2nd location">
</div>
</div>
<br></br>
<div class="row">
<div class="col-md-6">
<input type="text" class="form-control" id="locations_location3" placeholder="Enter address of the 3rd location">
</div>
<div class="col-md-6">
<input type="text" class="form-control" id="locations_location4" placeholder="Enter address of the 4th location">
</div>
</div>
<br></br>
<div class="row" style="text-align:center">
<div class="col-md-6">
<input type="text" class="form-control" id="locations_location5" placeholder="Enter address of the 5th location">
</div>
</div>
<br></br>
<div class="row">
<div id="locationField">
<input type="text" class="form-control" id="locations_cityField" placeholder="Enter a city" type="text" />
</div>
<div id="rangeField">
<input type="text" class="form-control" id="locations_rangeField" placeholder="Enter a search radius in meters (from the city center)" type="text" />
</div>
</div>
<div style="text-align:center">
<div id="map" style="width: 800px; height: 400px;"></div>
</div>
<button id="button_searchhotels" class="btn btn-success btn-lg">Search</button>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBVVnR7yKErwMDd6yC-GzVpRXFvNTtoKhQ&signed_in=true&libraries=places,geometry&callback=initSearchButtonListener"
async defer></script>
答案 0 :(得分:0)
地理编码器是异步的,您无法从其回调函数返回任何内容。当/可用时,您必须使用回调函数内的数据。重复How do I return the response from an asynchronous call?
这是不正确的:
function geocodeAddress(geocoder, address) {
console.log("address " + address);
console.log("geocoder " + geocoder);
geocoder.geocode({
'address': address
}, function(results, status) {
if (status === google.maps.GeocoderStatus.OK) {
var coords = results[0].geometry.location.toString();
console.log("CoordsRaw: " + coords)
var coordsNoFirst = coords.substring(1);
var coordsNoLast = coordsNoFirst.slice(0, -1);
cityCoordinates = coordsNoLast;
console.log(cityCoordinates);
//*********** this will not do anything useful **********
return results[0].geometry.location;
//*******************************************************
} else {
alert('Could not convert an address to latitude/longitude for the google maps API: ' + status);
}
});
}