我希望标题甚至可以理解。我有一个比较两个值的函数,其中一个值是第一个值的平均值。
基本上,我想找到n个标记的Long,Lat和中心标记之间的距离。我有一个循环将我的“results”变量推送到一个数组,并在循环结束时找到一个平均Lat,Long创建一个中心点。问题是我想找到每个“结果”和中心点之间的距离,但是在中间循环中,平均标记尚未最终确定。
更难解释而不是展示;我在这里设置了一个演示;要查看我的意思,请单击结果窗格中的“更新”按钮:http://jsfiddle.net/Cory2711/m55Ef/。你会看到的 从加利福尼亚发出的圆圈是正确的,因为它是最后一个圆圈(找到了完整的平均点)。来自纽约的圆圈是在中环,因此有一个不完整的平均标记来测量。
我的Javascript(问题集中在“标记”部分:
//GLOBAL VARIABLES
var gMapAPIKey = 'AIzaSyBUlnM6c7LqCR79UM9mTKvSNK6V7gzKsmE';
var namearray = document.getElementsByName("name");
var form = document.getElementById("addressform");
var addBtn = document.getElementById("addperson");
//GOOGLE MAPS API SCRIPTS
var streetarray = document.getElementsByName("street");
var cityarray = document.getElementsByName("city");
var geocoder;
var map;
var results;
var mapArray = new Array();
var AvgLat = 0;
var AvgLng = 0;
var j;
var newLatLng;
var dynamicRadius;
function initialize() {
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(-34.397, 150.644);
var mapOptions = {
zoom: 3,
//centered on Carrollton, Texas -- Change lat,long values to change initial map area
center: new google.maps.LatLng(32.999173, -96.897413)
}
//change Id reference to the div/container that contains the google map
map = new google.maps.Map(document.getElementById('map'), mapOptions);
}
function codeAddress() {
//Loop through and concate street and city values to find long,lat values for all fields
for (var cName = 0; cName < namearray.length; cName++) {
var address = streetarray[cName].value + cityarray[cName].value;
//start geocode copy & paste text from API reference
geocoder.geocode({
'address': address
}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var results = results[0].geometry.location;
map.setCenter(results);
console.log(results);
var marker = new google.maps.Marker({
map: map,
position: results,
});
//Push lng/lat locations to the mapArray and find AvgLat/Lngs
mapArray.push(results);
var j = mapArray.length;
AvgLat = (AvgLat + results.lat());
AvgLng = (AvgLng + results.lng());
console.log(mapArray, AvgLat, AvgLng, j)
//Begin Marker Scripts
var markerCircle = new google.maps.Circle({
center: results,
radius: 15000,
strokeColor: "#0000FF",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#0000FF",
fillOpacity: 0.4
})
var centerLocation = {
lat: AvgLat / j,
lng: AvgLng / j,
}
var newLatLng = new google.maps.LatLng(centerLocation.lat, centerLocation.lng);
var dynamicRadius = google.maps.geometry.spherical.computeDistanceBetween (results, newLatLng);
if (j == namearray.length) {
markerCircle.setRadius(dynamicRadius*1.15)
map.setCenter(newLatLng);
var centerMarker = new google.maps.Marker({
position: newLatLng,
map: map,
title: "Center Marker",
})
var centerCircle = new google.maps.Circle({
center: newLatLng,
radius: 15000,
strokeColor: "#0000FF",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#0000FF",
fillOpacity: 0.4,
map: map,
})
}
markerCircle.setRadius(dynamicRadius*1.15)
markerCircle.setMap(map);
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
}
}
//Initialize the first map on load -- When form is submitted geocode addresses and places markers on the map
google.maps.event.addDomListener(window, 'load', initialize);
form.addEventListener("submit", codeAddress, false);
addBtn.addEventListener("click", addPerson, false);
答案 0 :(得分:1)
我的第一个想法是,您不仅限于将数据循环一次。循环后数据仍然存在(除非您在此过程中更改或销毁它)。
所以,你要使用两个循环。
第一个循环计算中心点。
第二个循环计算该点的所有距离。
但是当我查看你的代码时,我发现它还有更多的东西。
在主循环中迭代namearray
,循环为此数组的每个元素调用geocoder.geocode()
。然后在地理编码器回调中进行工作。
有趣的是,这段代码实际上并不是主循环的一部分。它出现在该循环内部,但随后会逐渐调用它,因为地理编码响应会逐一返回。
因此,我们假设地理编码中没有错误(错误的假设,但我们将暂时运行它)。您的地理编码器回调已将每个地理编码结果推送到mapArray
。所以你可以做的是让这个回调代码只这样做而不做任何中心/圆计算。所以你的地理编码调用可能看起来更像这样:
geocoder.geocode({
'address': address
}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
mapArray.push({ latLng: results[0].geometry.location });
AvgLat += results.lat();
AvgLng += results.lng();
} else {
mapArray.push({ error: status });
++nErrors;
}
// Might want to update a progress indicator here
// if the geocoding takes a while?
if( mapArray.length == namearray.length ) {
// Everything is geocoded, now get to work
drawMap();
}
});
(nErrors
应在使用var nErrors = 0;
初始化其他变量的循环上方定义。
然后完全在当前主循环之外,添加此功能:
function drawMap() {
if( nErrors ) {
// complain about error
return;
}
var center = {
lat: AvgLat / j,
lng: AvgLng / j,
};
map.setCenter( new google.maps.LatLng( center.lat, center.lng ) );
for( var i = 0; i < mapArray.length; i++ ) {
// Create marker and draw circle here
}
}
所以其他几点。首先,以这种方式计算平均纬度/经度听起来不太合适。我会考虑(和测试)标记是0°和180°经线的不同侧面的情况。你可能在那里,我从不指望它!
实际上你想要的是“平均”纬度/长度吗? (可能只是问。)如果你有很多标记在彼此附近并且在某个距离上有很少的标记(例如CA中的10个标记和NY中的1个标记),则“平均”将非常接近该标记簇。这可能是你想要的,但如果没有,还有其他方法来计算各种“中心”。
例如,一种常见方法是创建一个空的LatLngBounds
对象,然后使用您收到的每个位置扩展这些边界。所以在你的其他变量初始化的顶部,你要添加:
var bounds = new google.maps.LatLngBounds;
然后在每个成功的地理编码回调中,你将替换它:
AvgLat += results.lat();
AvgLng += results.lng();
使用:
bounds.extend( results );
然后在drawMap()
中替换它:
var center = {
lat: AvgLat / j,
lng: AvgLng / j,
};
map.setCenter( new google.maps.LatLng( center.lat, center.lng ) );
使用:
map.fitBounds( bounds );
var center = bounds.getCenter();
如果您需要这些单独的值,请使用center.lat()
和center.lng()
- 但是在您拥有newLatLng
的地方,您现在可以直接使用center
,因为它 一个LatLng
对象。
即使您确实想要使用圆圈计算的“平均”点,您也可以使用此边界框方法进行地图居中,而不是将地图置于计算平均值的中心。
最后一点是要注意地理编码的速率限制和限制。也许您可以使用少量标记,但是您可能需要在它们之间使用时间间隔进行地理编码调用,而不是将它们全部放入硬循环中。