【发布时间】:2020-04-26 16:36:07
【问题描述】:
编辑:我已经实现了我可能的解决方案 1,但它可以工作,但是如上所述,它不是最好的解决方案,所以我仍然会对其他建议感兴趣。
我有一个 delphi VCL 应用程序,可以将 mapbox 地图加载到 Twebbrowser 组件中。我使用地图作为输入来获取 GPS 坐标和街道地址。
javascript使您可以单击地图以放置标记,也可以将其拖动等。
我有一个 javascript 函数,它对标记位置执行反向地理编码并将地址保存到变量中。
function getAddress(err, data){
var center = data.features[0].center;
streetAddress = data.features[0].place_name;
myMarker.setPopupContent("Position: <br /> lat = " + center[0] + "<br /> long = " + center[1] + "<br /> Address: " + streetAddress);
}
function delphiLocate(){
geocoder.reverseQuery(myMarker.getLatLng(), getAddress);
gpsCoords = myMarker.getLatLng().toString();
}
可以通过单击标记或通过我的 Delphi 程序调用此函数。
我的 delphi 代码也可以从 javascript 中读取地址变量。
procedure TfrmCreateSpot.getSpotPos;
var
doc: OleVariant;
begin
doc := WebBrowser1.document;
doc.parentwindow.execScript('delphiLocate()', 'JavaScript');
sGpsCoords := doc.parentwindow.gpsCoords;
sGpsCoords := copy(sGpsCoords, Pos('(', sGpsCoords) + 1);
delete(sGpsCoords, Pos(')', sGpsCoords), 1);
sStreetAddress := doc.parentwindow.streetAddress;
end;
此 getSpotPos 过程在单击按钮以确认位置时调用。
问题是 geolocate 需要一段时间才能返回结果,并且当它返回时,我的程序已经记录了最后一个标记位置的信息。
如何确保从当前标记位置获取地址?
可能的解决方案:
1) 如果我在每次移动标记时调用定位函数,那么地理定位应该在用户单击确认按钮之前完成。然而,这似乎是一个相当 hacky 可能不可靠的解决方案,而且它可能使用比必要更多的地理定位请求(这对我来说不是问题,因为它只是一个学校项目,不会超过我的 100 000 限制,但是我喜欢实施最好的解决方案。
2) 在返回结果时在 javaScript 中创建一个标志,在我的 Delphi 代码中我可以使用计时器来检查该标志是否为真,然后请求结果。
这是完整的 Html 脚本
<title>Map</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.mapbox.com/mapbox.js/v3.3.0/mapbox.js'></script>
<link href='https://api.mapbox.com/mapbox.js/v3.3.0/mapbox.css' rel='stylesheet' />
<style>
body { margin:0; padding:0; width : 100%; }
#map {position : absolute; top:0; bottom:0; width: 100%; }
</style>
</head>
<body>
<div id='map'></div>
<script>
function mapClick(e){
if (!locked){
myMarker.setLatLng(e.latlng);
}
}
function locate(e) {
geocoder.reverseQuery(e.latlng, getAddress);
gpsCoords = e.latlng.toString();
}
function getAddress(err, data){
var center = data.features[0].center;
streetAddress = data.features[0].place_name;
myMarker.setPopupContent("Position: <br /> lat = " + center[0] + "<br /> long = " + center[1] + "<br /> Address: " + streetAddress);
}
function centerMarker(e){
if (!locked){
var coords = e.feature.geometry.coordinates;
myMarker.setLatLng([coords[1],coords[0]]);// lat lng are swapped
}
}
function delphiLocate(){
geocoder.reverseQuery(myMarker.getLatLng(), getAddress);
gpsCoords = myMarker.getLatLng().toString();
}
var locked = false;
function toggleLock(){
if (!locked) {
myMarker.setIcon(redIcon);
myMarker.dragging.disable();
locked = true;
} else {
myMarker.setIcon(blueIcon);
myMarker.dragging.enable();
locked = false;
}
}
L.mapbox.accessToken = 'pk.eyJ1IjoiZ3JlZW5vbGl2ZSIsImEiOiJjazk4N3hpcngwMDU0M2VvMGhydGw2Z2YxIn0.wvwQzgwsaujmkNOX7Bs47A';
var map = L.mapbox.map('map')
.setView([-30.487,23.181], 6)
.addLayer(L.mapbox.styleLayer('mapbox://styles/greenolive/ck9fi6dbk3hag1itg5aem2ypi'));
var geocoderControl = L.mapbox.geocoderControl('mapbox.places',{autocomplete : true}).addTo(map);
var geocoder = L.mapbox.geocoder('mapbox.places');
var blueIcon = L.icon({
iconUrl: 'blueMarker.png',
iconSize: [40, 40], // size of the icon
iconAnchor: [20, 40], // point of the icon which will correspond to marker's location
popupAnchor: [0, -40] // point from which the popup should open relative to the iconAnchor
});
var redIcon = L.icon({
iconUrl: 'redMarker.png',
iconSize: [40, 40], // size of the icon
iconAnchor: [20, 40], // point of the icon which will correspond to marker's location
popupAnchor: [0, -40] // point from which the popup should open relative to the iconAnchor
});
var myMarker = L.marker(map.getCenter(), { draggable : true, icon : blueIcon}).addTo(map).bindPopup("Position: <br /> lat = " + map.getCenter().lat + "<br /> long = " + map.getCenter().lng+ "<br /> Address: ");
var gpsCoords;
var streetAddress;
map.on('click',mapClick);
myMarker.on('click', locate);
geocoderControl.on('select', centerMarker);
</script>
</body>
</html>
【问题讨论】:
-
干得好。但是就像您的建议一样,我认为您可以在移动标记时将 streetAddress 设为空,这样在 geolocate 函数返回之前它不会显示地址。
-
@R.Hoek 我不确定这对我有什么帮助,我需要我的 Delphi 程序知道函数何时返回
-
嗯,最好编辑你的问题,因为现在的问题是“知道函数是否返回”,在这种情况下,我的想法(或你的标志想法)就足够了。但是想要“在函数返回时在 delphi 中得到通知”(就像一个事件)-对吗?
-
@OliverHope 如果你想要一些类似事件的东西,也许这个线程可以帮助javascript.developreference.com/article/20717415/…
标签: javascript html delphi mapbox vcl