地理编码器调用在 for 循环中不起作用
geocoder call does not work in for loop
我正在研究使用最后位置地址、名称、时间等跟踪多个设备的项目。为了显示地址,我正在使用反向地理编码(最后位置经纬度来自 mysql db)。代码适用于单个设备跟踪,但是当我尝试一次显示所有设备时,它只显示第一个设备地址。之后,for 循环停止。我不知道我哪里错了。如果有人知道,请指出我的错误并纠正我。这是我的完整 javascript 代码。
<script type="text/javascript">
function load() {
var abc;
var pqr;
function getLocation() {
navigator.geolocation.getCurrentPosition(showPosition);
}
function showPosition(position) {
abc = position.coords.latitude;
pqr = position.coords.longitude;
googlemap(abc, pqr);
}
getLocation();
}
function googlemap(lat, lng) {
var x = document.getElementById("myForm");
var text = '';
for (var k = 0; k < x.length; k++) {
text += x[k].value;
if (k != (x.length - 1)) {
text += ",";
}
}
var names = new Array();
var colors = new Array();
var imeis = new Array();
var times = new Array();
var point;
var map = new google.maps.Map(document.getElementById("map"), {
center: new google.maps.LatLng(lat, lng),
zoom: 6,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var iconsetngs = {
path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW
};
setInterval(function () {
downloadUrl("points.php?data=" + text, function (data) {
var xml = data.responseXML;
var points = xml.documentElement.getElementsByTagName("point");
flightPlanCoordinates = new Array();
var imo = '';
var w = -1;
for (var i = 0; i < points.length; i++) {
if (parseFloat(points[i].getAttribute("imei")) != imo) {
names.push(points[i].getAttribute("name"));
times.push(points[i].getAttribute("time"));
colors.push(points[i].getAttribute("color"));
imeis.push(parseFloat(points[i].getAttribute("imei")));
imo = parseFloat(points[i].getAttribute("imei"));
w++;
flightPlanCoordinates[w] = new Array();
}
point = new google.maps.LatLng(
parseFloat(points[i].getAttribute("lat")),
parseFloat(points[i].getAttribute("lon"))
);
flightPlanCoordinates[w].push(point);
}
for (var j = 0; j < imeis.length; j++) {
var flightPath = new google.maps.Polyline({
path: flightPlanCoordinates[j],
geodesic: true,
strokeColor: colors[j],
strokeOpacity: 1.0,
strokeWeight: 2,
icons: [{
icon: iconsetngs,
repeat: '35px',
offset: '100%'}]
});
var geocoder = new google.maps.Geocoder();
geocoder.geocode({'latLng': flightPlanCoordinates[j][(flightPlanCoordinates[j].length) - 1]}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
map.setZoom(7);
var marker = new google.maps.Marker({
position: flightPlanCoordinates[j][(flightPlanCoordinates[j].length) - 1],
map: map
});
var contentString = names[j] + times[j] + results[1].formatted_address;
var infowindow = new google.maps.InfoWindow({
content: contentString
});
infowindow.open(map, marker);
} else {
alert('No results found');
}
} else {
alert('Geocoder failed due to: ' + status);
}
});
flightPath.setMap(map);
geocoder.setMap(map);
}
});
names = [];
imeis = [];
times = [];
colors = [];
flightPlanCoordinates = [];
}, 10 * 1000);
}
function downloadUrl(url, callback) {
var request = window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest;
request.onreadystatechange = function () {
if (request.readyState == 4) {
request.onreadystatechange = doNothing;
callback(request, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
function doNothing() {
} </script>
<body onload="load();">
<form method="post" id="myForm" class="myForm" name="myForm">
<select name="dvc">
<option value="all">All</option>
<?php
$qry = mysql_query("SELECT * FROM devices");
while ($row = mysql_fetch_array($qry)) {
?>
<option value="<?php echo $row['device_imei']; ?>"><?php echo $row['device_name']; ?></option>
<?php } ?>
</select>
<input type="date" name="exct" value="<?php echo $date; ?>"/>
From:
<input type="date" name="from" />
To:
<input type="date" name="to" />
</form>
<button onclick="load();">Submit</button>
<div id="map" style="width: 100%; height: 100%"></div>
</body>
当前的变量取决于执行回调时 j
的值,这可能要等到实际的 for
循环结束并且 j
达到最大值时才会发生价值。相反,你需要让他们有自己的范围。 Javascript 没有块作用域,因此您需要将其包装在另一个函数调用中,如下所示:
var createGeocodeCallback = function(n){
return function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
map.setZoom(7);
var marker = new google.maps.Marker({
position: flightPlanCoordinates[n][(flightPlanCoordinates[n].length) - 1],
map: map
});
var contentString = names[n] + times[n] + results[n].formatted_address;
var infowindow = new google.maps.InfoWindow({
content: contentString
});
infowindow.open(map, marker);
} else {
alert('No results found');
}
} else {
alert('Geocoder failed due to: ' + status);
}
};
}
然后在 googlemap()
函数的第二个循环中,您可以这样做:
for (var j = 0; j < imeis.length; j++) {
var flightPath = new google.maps.Polyline({
path: flightPlanCoordinates[j],
geodesic: true,
strokeColor: colors[j],
strokeOpacity: 1.0,
strokeWeight: 2,
icons: [{
icon: iconsetngs,
repeat: '35px',
offset: '100%'}]
});
var geocoder = new google.maps.Geocoder();
geocoder.geocode({'latLng': flightPlanCoordinates[j][(flightPlanCoordinates[j].length) - 1]}, createGeocodeCallback(j));
flightPath.setMap(map);
geocoder.setMap(map);
}
将数据存储为一组要处理的对象(并访问 item.name
、item.time
、item.flightPlanCoordinates
等)可能会更容易、更清晰,因此您可以使用 Array.forEach()
创建回调,它会为您处理整个范围。
我正在研究使用最后位置地址、名称、时间等跟踪多个设备的项目。为了显示地址,我正在使用反向地理编码(最后位置经纬度来自 mysql db)。代码适用于单个设备跟踪,但是当我尝试一次显示所有设备时,它只显示第一个设备地址。之后,for 循环停止。我不知道我哪里错了。如果有人知道,请指出我的错误并纠正我。这是我的完整 javascript 代码。
<script type="text/javascript">
function load() {
var abc;
var pqr;
function getLocation() {
navigator.geolocation.getCurrentPosition(showPosition);
}
function showPosition(position) {
abc = position.coords.latitude;
pqr = position.coords.longitude;
googlemap(abc, pqr);
}
getLocation();
}
function googlemap(lat, lng) {
var x = document.getElementById("myForm");
var text = '';
for (var k = 0; k < x.length; k++) {
text += x[k].value;
if (k != (x.length - 1)) {
text += ",";
}
}
var names = new Array();
var colors = new Array();
var imeis = new Array();
var times = new Array();
var point;
var map = new google.maps.Map(document.getElementById("map"), {
center: new google.maps.LatLng(lat, lng),
zoom: 6,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var iconsetngs = {
path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW
};
setInterval(function () {
downloadUrl("points.php?data=" + text, function (data) {
var xml = data.responseXML;
var points = xml.documentElement.getElementsByTagName("point");
flightPlanCoordinates = new Array();
var imo = '';
var w = -1;
for (var i = 0; i < points.length; i++) {
if (parseFloat(points[i].getAttribute("imei")) != imo) {
names.push(points[i].getAttribute("name"));
times.push(points[i].getAttribute("time"));
colors.push(points[i].getAttribute("color"));
imeis.push(parseFloat(points[i].getAttribute("imei")));
imo = parseFloat(points[i].getAttribute("imei"));
w++;
flightPlanCoordinates[w] = new Array();
}
point = new google.maps.LatLng(
parseFloat(points[i].getAttribute("lat")),
parseFloat(points[i].getAttribute("lon"))
);
flightPlanCoordinates[w].push(point);
}
for (var j = 0; j < imeis.length; j++) {
var flightPath = new google.maps.Polyline({
path: flightPlanCoordinates[j],
geodesic: true,
strokeColor: colors[j],
strokeOpacity: 1.0,
strokeWeight: 2,
icons: [{
icon: iconsetngs,
repeat: '35px',
offset: '100%'}]
});
var geocoder = new google.maps.Geocoder();
geocoder.geocode({'latLng': flightPlanCoordinates[j][(flightPlanCoordinates[j].length) - 1]}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
map.setZoom(7);
var marker = new google.maps.Marker({
position: flightPlanCoordinates[j][(flightPlanCoordinates[j].length) - 1],
map: map
});
var contentString = names[j] + times[j] + results[1].formatted_address;
var infowindow = new google.maps.InfoWindow({
content: contentString
});
infowindow.open(map, marker);
} else {
alert('No results found');
}
} else {
alert('Geocoder failed due to: ' + status);
}
});
flightPath.setMap(map);
geocoder.setMap(map);
}
});
names = [];
imeis = [];
times = [];
colors = [];
flightPlanCoordinates = [];
}, 10 * 1000);
}
function downloadUrl(url, callback) {
var request = window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest;
request.onreadystatechange = function () {
if (request.readyState == 4) {
request.onreadystatechange = doNothing;
callback(request, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
function doNothing() {
} </script>
<body onload="load();">
<form method="post" id="myForm" class="myForm" name="myForm">
<select name="dvc">
<option value="all">All</option>
<?php
$qry = mysql_query("SELECT * FROM devices");
while ($row = mysql_fetch_array($qry)) {
?>
<option value="<?php echo $row['device_imei']; ?>"><?php echo $row['device_name']; ?></option>
<?php } ?>
</select>
<input type="date" name="exct" value="<?php echo $date; ?>"/>
From:
<input type="date" name="from" />
To:
<input type="date" name="to" />
</form>
<button onclick="load();">Submit</button>
<div id="map" style="width: 100%; height: 100%"></div>
</body>
当前的变量取决于执行回调时 j
的值,这可能要等到实际的 for
循环结束并且 j
达到最大值时才会发生价值。相反,你需要让他们有自己的范围。 Javascript 没有块作用域,因此您需要将其包装在另一个函数调用中,如下所示:
var createGeocodeCallback = function(n){
return function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[1]) {
map.setZoom(7);
var marker = new google.maps.Marker({
position: flightPlanCoordinates[n][(flightPlanCoordinates[n].length) - 1],
map: map
});
var contentString = names[n] + times[n] + results[n].formatted_address;
var infowindow = new google.maps.InfoWindow({
content: contentString
});
infowindow.open(map, marker);
} else {
alert('No results found');
}
} else {
alert('Geocoder failed due to: ' + status);
}
};
}
然后在 googlemap()
函数的第二个循环中,您可以这样做:
for (var j = 0; j < imeis.length; j++) {
var flightPath = new google.maps.Polyline({
path: flightPlanCoordinates[j],
geodesic: true,
strokeColor: colors[j],
strokeOpacity: 1.0,
strokeWeight: 2,
icons: [{
icon: iconsetngs,
repeat: '35px',
offset: '100%'}]
});
var geocoder = new google.maps.Geocoder();
geocoder.geocode({'latLng': flightPlanCoordinates[j][(flightPlanCoordinates[j].length) - 1]}, createGeocodeCallback(j));
flightPath.setMap(map);
geocoder.setMap(map);
}
将数据存储为一组要处理的对象(并访问 item.name
、item.time
、item.flightPlanCoordinates
等)可能会更容易、更清晰,因此您可以使用 Array.forEach()
创建回调,它会为您处理整个范围。