我要做的事情:
-
只允许在一个国家上空移动的可拖动标记。
-
拖动结束后,位置显示在输入文本中。
信息:将标记锁定在一个国家有效,但并不完美,当我多次快速移动标记时,甚至在允许的国家。它回到了它的立场,这种情况应该发生在其他国家之上。
两个必需的东西的每一部分都是单独工作的,当它们组合在一起作为下面的代码时,它们就不起作用了。问题一定出在(dragend)监听器上,但我找不到它是什么。
<script src="http://maps.googleapis.com/maps/api/js?libraries=geometry&sensor=false"></script>
<script>
var map = null;
var marker = null;
var country = 'DE';
function updateMarkerAddress(str) {
document.getElementById('address').value = str;
}
function initialize() {
var startDragPosition = null;
var mapOptions = {
zoom: 6,
center: new google.maps.LatLng(50.8,10.3),
mapTypeId: google.maps.MapTypeId.TERRAIN
};
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
marker = new google.maps.Marker({
position: new google.maps.LatLng(48.784084,9.181635),
map: map,
draggable: true
});
var myGeocoder = new google.maps.Geocoder();
google.maps.event.addListener(marker,'dragstart',function(event) {
startDragPosition = marker.getPosition();
});
google.maps.event.addListener(marker,'dragend',function(event) {
myGeocoder.geocode({'latLng': marker.getPosition()}, function(responses,results, status) {
if (status == google.maps.GeocoderStatus.OK && results[1]) {
var countryMarker = addresComponent('country', results[1], true);
if (country != countryMarker) {
marker.setPosition(startDragPosition);
}
}
else {
marker.setPosition(startDragPosition);
}
if (responses && responses.length > 0)
{
updateMarkerAddress(responses[0].formatted_address);
}
else
{
updateMarkerAddress('Cannot determine address at this location.');
}
});
});
}
function addresComponent(type, geocodeResponse, shortName) {
for(var i=0; i < geocodeResponse.address_components.length; i++) {
for (var j=0; j < geocodeResponse.address_components[i].types.length; j++) {
if (geocodeResponse.address_components[i].types[j] == type) {
if (shortName) {
return geocodeResponse.address_components[i].short_name;
}
else {
return geocodeResponse.address_components[i].long_name;
}
}
}
}
return '';
}
</script>
<style>
#map-canvas {
height:400px;
}
</style>
<input type="text" id="address">
一般的问题是myGeocoder.geocode()的回调。该函数只返回两个变量-响应和状态。因此,下面的代码应该可以工作。
google.maps.event.addListener(marker,'dragend',function(event) {
myGeocoder.geocode({'latLng': marker.getPosition()}, function(responses,status) {
if (status == google.maps.GeocoderStatus.OK && responses[0]) {
var countryMarker = addresComponent('country', responses[0], true);
if (country != countryMarker) {
marker.setPosition(startDragPosition);
}
} else {
marker.setPosition(startDragPosition);
}
if (responses && responses.length > 0) {
updateMarkerAddress(responses[0].formatted_address);
} else {
updateMarkerAddress('Cannot determine address at this location.');
}
});
});
快速多次移动标记可能会破坏代码,原因有两个。
- geocode()函数是异步的,因此如果您创建在短时间间隔内连续回调,完成顺序可以不同于创建顺序
- 谷歌地理编码器有一个速率限度如果查询过多,速度过快,它将停止工作
这两个问题都可以通过将代码重新构造成这样来解决。(注意:这部分代码使用jquery,所以您可能也必须包含它。)
//wrap the geocoder in a function.
function geocode (marker,country) {
myGeocoder.geocode('query', function(){ ... } );
}
// call the geocoder with a timeout and clear the timeout everytime the geocoder is called again.
google.maps.event.addListener(marker,'dragend',function(event) {
clearTimeout($.data(marker,'timer'));
$(marker).data('timer', setTimeout(function(){geocode(marker,country)}, 1000));
});
上述方法将确保,无论您移动标记的速度有多快,地理编码功能都只能在它们之间的最小间隙(在上述情况下为1000ms)下触发。