将地图框地理编码结果从Javascript返回到Delphi

问题描述 投票:1回答: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中读取address变量。

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过程在单击按钮以确认位置时调用。问题是,地理位置定位器需要一段时间才能返回结果,并且到它返回时,我的程序已经记录了最后一个标记位置的信息。

如何确保我从当前标记位置获得地址?

可能的解决方案:

1)如果每次移动标记时都调用locate函数,则在用户单击确认按钮之前,地理定位应该已经完成​​。但是,这似乎是一个很棘手的解决方案,可能不可靠,而且它可能会使用比必要更多的地理位置请求(这对我来说不是问题,因为这只是一个学校项目,不会超过我的100000上限,但是id希望实施最佳解决方案。

2)在javaScript中创建一个返回结果时为true的标志,在我的Delphi代码中,我可以使用计时器检查该标志是否为true,然后请求结果。

这里是完整的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>
javascript html delphi mapbox vcl
1个回答
0
投票

似乎您在此处设置变量gpsCoords

        function delphiLocate(){
        geocoder.reverseQuery(myMarker.getLatLng(), getAddress);
        gpsCoords = myMarker.getLatLng().toString();
    }

调用delphiLocate函数后将在Delphi脚本中进行访问。因此,应更新JS中的gpsCoords变量。但是,在您的Delphi脚本中,您仍然需要在调用doc之前访问已加载的delphiLocate对象。该对象仍应具有旧的gpsCoords

您可以在调用doc之后尝试重新加载delphiLocate对象吗?

  doc := WebBrowser1.document;

  doc.parentwindow.execScript('delphiLocate()', 'JavaScript');
doc := WebBrowser1.document;
  sGpsCoords := doc.parentwindow.gpsCoords;
© www.soinside.com 2019 - 2024. All rights reserved.