代码之家  ›  专栏  ›  技术社区  ›  flash

如何使用google maps api创建一个在特定半径内搜索项目的表单?

  •  9
  • flash  · 技术社区  · 6 年前

    我正在一个 website上工作,我想在其中围绕当前位置或一些手动地址在谷歌地图上画一个圈。

    • 用户将有选择权决定是要围绕当前位置进行圈选,还是要提供一些随机地址。 (用户可以选择将手动地址放在当前位置内,如下图所示,在图像中)

    • 现在,我们还需要确保圆的半径是特定的( 0-20/70km,从当前位置开始),并且用户也需要确定这一点。( 当前位置下方的线将决定用户可以在0-70km处移动的半径

    例如:用户希望从当前位置创建一个到30公里的圆,或者用户希望从某个随机地址创建一个到20公里的圆。
    BR/>

    我用来创建搜索半径搜索栏的HTML代码是

    <div class=“input searchradius”>
    <input class=“form control search_radius mb-4”type=“text”placeholder=“search radius”>
    &L/DIV & GT;
    < /代码> 
    
    
    问题陈述:

    (1)I am knowing what changesI need to make or code I need to add.so that the items are being searched around a specific radius.我认为,我需要集成代码google maps circle但是我不确定我如何才能做到这一点。

    (2)on hit of search radius on thewebsite.The following options/screen will appear at the bottom:(搜索半径点击后,网站上出现)

    .

    例如:用户希望从当前位置创建一个到30公里的圆,或者用户希望从某个随机地址创建一个到20公里的圆。

    enter image description here

    我用来生成一个搜索半径的搜索栏为:

    <div class="input-searchradius">
       <input class="form-control search_radius mb-4" type="text" placeholder="search radius">
    </div>
    



    问题陈述:

    (1)我想知道有什么变化我需要制作或编码我需要添加以便在特定半径范围内搜索项目。我想,我需要整合代码Google Maps circle但我不知道我该怎么做。

    (2)搜索半径命中网站下面将显示以下选项/屏幕:

    2 回复  |  直到 6 年前
        1
  •  2
  •   SirPeople    6 年前

    让我们试着给你一些第一步,我不会对整个应用程序进行编码,而是给你一些关于如何解决你所拥有的小的子问题的指导:

    在地图中添加圆

    嗯,对于这个,您有许多不同的输入选项,但最重要的部分是addcircle函数:

    function addCircle(center){
        circle = new google.maps.Circle({
            map: map, //The existing map
            center: center,
            radius: 200, //This will be modified afterwards
            zindex: 100
        });
    }
    

    中心可能来自 click 例如:

    // Area is wherever you want to attach the click, either a polygon, a map...
    google.maps.event.addListener(area, "click", function(event) {
            addCircle(event.latLng);
    });
    

    或者通过得到某个地址的位置( This is documented as well )或任何方法(拖放圆,拖动标记blablablabla)

    添加动态半径

    如果我们知道的话 the radius of the Circle is given in meters 那么很容易给addcircle函数给出正确的半径。例如,20公里-20 000米。所以在调用addcircle时,您只需要访问radius(它可以是一个参数,一个全局变量…你的选择。

    我们已经完成了绘制部分,现在让我们在该圆内搜索。

    仅获取圆内的标记

    这里有一个先决条件,就是要有地图上的所有标记。您可能有一系列从数据库中获取的位置,或者 get the markers from Google Maps API (例如place search)。

    在此之后,您必须计算这些标记与给定中心之间的距离,并检查距离是否小于半径(用 computeDistanceBetween 很容易),所以您将知道哪些标记对您有效。

    const markers = [//array of my valid markers with position];
    markers.filter( (marker) => 
        google.maps.geometry.spherical.computeDistanceBetween(marker.getPosition(), center.getPosition()) < radius; // Filter the markers which distance is bigger than radius;
    

    剩下的工作也应该很容易, place the markers in the map 用这些信息做你想做的事。

    额外的

    作为进一步的帮助,有一对示例/答案可能对您有用:

    Full Google Map API example 非常简单的一步一步的指导。

    Radius search using places ,关于如何进行半径搜索的一个很好的答案。

    Example of radius search ,打开F12并调试代码(如果您愿意),但很容易理解。

    edit**:我没有意识到其中的2个链接也在评论中指出。

        2
  •  1
  •   McMurphy    6 年前

    我建议使用工作线程进行搜索,通过在后台进行搜索来释放UI线程。如果用户移动圆圈或展开/收缩圆圈,这也很有用,因为可以放弃以前搜索/呈现的匹配标记,

    importScripts("Tier3Toolbox.js");
    
    var currVintage = 0;
    var inBounds = false;
    var facFilter = [];
    var imageProlog = "<div style='height:5em; width:5em; display:inline-block;vertical-align:middle;'>" +
                      "<img style='height:100%; width: 100%; max-height:100%; max-width:100%' src='";
    var imageEpilog = "' ></div>";
    var facilityTable, lineBreak;
    
    self.addEventListener('message', function(e) 
    {
      var data = e.data;
      switch (data.cmd) {
        case 'init':
          initThread(data.load);
          break;
        case 'initFilter':
          for (var i=0; i<data.filterTable.length; i++) {
            facFilter[data.filterTable[i].locTypeId] = {'icon':data.filterTable[i].icon};
          }
          break;
        case 'filter':
          facFilter = [];
          for (var i=0; i<data.filterTable.length; i++) {
            if (data.filterTable[i].facSelected)
              facFilter[data.filterTable[i].locTypeId] = {'icon':data.filterTable[i].icon};
          }
          break;
        case 'search':
          var searchVintage = ++currVintage;
          var tableSearch = new searcher(searchVintage, data);
          break;
        case 'reset':
          reset();
          self.postMessage({'reset': true});
          break;
        case 'stop':
          self.postMessage({'success' : true});
          self.close(); 
          break;
        default:
          self.postMessage({'success' : false, 'msg' : data.msg});
      };
    }, false);
    
    function initThread(msg) 
    {
        facilityTable = JSON.parse(msg);
        reset();
    
        self.postMessage({'success' : true, 
                          'cnt'     : facilityTable.length
                        });     
    }   
    
    function reset() 
    {
        for (var i=0; i<facilityTable.length; i++) {
            facilityTable[i].visible=false
        }
        currVintage = 0;
    }   
    
    function searcher(searchVintage, msg)
    {
        var myVintage = searchVintage;
        var facIndex  = -1;
        var msg       = msg;
    
        var checkLoop = function()
        {
            if (myVintage != currVintage)
                return;
    
            if (++facIndex == facilityTable.length)
                return;
    
            inBounds = geoFencer.call(this, msg);
    
            if (inBounds) {
                var facMatch = 0;
                var bubbleHTML = "";
                for (var i=0; i<facilityTable[facIndex].facilities.length; i++){
                    var currFac = facilityTable[facIndex].facilities[i];
                    if (facFilter[currFac.locTypeId] != undefined) {
                        if (facMatch != 0) {
                            lineBreak = (facMatch / 3);
                            if (lineBreak == lineBreak.toFixed(0)) {
                                bubbleHTML += "<br />";
                            }
                        }
                        facMatch++;
                        bubbleHTML += imageProlog + facFilter[currFac.locTypeId].icon + imageEpilog;
    
                    }
                }
                if (facMatch == 0) {
                    inBounds = false;
                }
            }
    
            if (inBounds != facilityTable[facIndex].visible) {
                self.postMessage({'match'       : inBounds,
                                  'facIndex'    : facIndex,
                                  'scopeVintage': msg.scopeVintage,
                                  'bubbleHTML'  : bubbleHTML,
                                  'success'     : true
                                }); 
                facilityTable[facIndex].visible = inBounds;
            }
    
            setTimeout(checkLoop,0);
        }
    
        var circleCheck = function(msg) 
        {
            var diff = Tier3Toolbox.calculateDistance(
                            msg.centerLat,
                            msg.centerLng,
                            facilityTable[facIndex].searchLat,
                            facilityTable[facIndex].searchLng);
    
            if (msg.radius > diff)
                return true;        
    
            return false;
        }
    
        var rectangleCheck = function(msg) 
        {
            if (facilityTable[facIndex].searchLat > msg.SWLat &&
                facilityTable[facIndex].searchLat < msg.NELat &&
                facilityTable[facIndex].searchLng > msg.SWLng &&
                facilityTable[facIndex].searchLng < msg.NELng)
                return true;        
    
            return false;
        }
    
        var GEOFENCER = [circleCheck,rectangleCheck];
        var geoFencer = GEOFENCER[msg.checker];
    
        setTimeout(checkLoop,0);
        return this;
    }
    

    “工具箱”功能包括:

        function Tier3Toolbox() 
    {
        return this;
    }
    
    Tier3Toolbox.EARTH_RADIUS = 6378137; /* Equitorial Radius instead of 6371000 */
    Tier3Toolbox.toRad = 
        function (num) {
            return num * Math.PI / 180;
        };  
    Tier3Toolbox.calculateDistance =
        function(lat1, lon1, lat2, lon2){
            var dLat = this.toRad(lat2 - lat1);
            var dLon = this.toRad(lon2 - lon1);
            var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(this.toRad(lat1)) * 
                    Math.cos(this.toRad(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
            var distance = this.EARTH_RADIUS * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
            return distance;
        }
    
    Tier3Toolbox.prototype.callAJAX = 
        function(url, method, callback, serverArgs) 
        {
            var callback = callback;
            var xmlhttp;
            var target = url;
            var args = (serverArgs != undefined) ? serverArgs : "";
            var postArgs = "";
            var callbackArgs = new Array();
    
            for (i = 4; i < arguments.length; i++) {
                callbackArgs[i - 3] = arguments[i];
            }
    
            if (window.XMLHttpRequest) {
                xmlhttp = new XMLHttpRequest();
            } else {
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
    
            callbackArgs[0] = xmlhttp;
    
            if (method.toUpperCase() == "GET") {
                target = target + "?" + args;
            } 
    
            xmlhttp.onreadystatechange = function () {
                if (xmlhttp.readyState == 4) {
                    if (xmlhttp.status == 200) {
                        callback.apply(this, callbackArgs)
                    } else {
                        throw new Error("Error making Ajax call to " + target + " Status = " + xmlhttp.status);
                    }
                }
            };
    
            xmlhttp.open(method, url, true);
            if (method.toUpperCase() == "POST") {
                xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
                postArgs = args;
            }
            xmlhttp.send(postArgs);
        }
    
    Tier3Toolbox.reportError =      
        function(error) 
        {
            var header  = error.header  || "Error";
            var message = error.message || "";
            var topWindow=window.top.document.open();
            topWindow.write("<!DOCTYPE html><html><body style='height: 100%;'><hr><h1>" + header + "</h1><hr>");
            topWindow.write("<h2>Please contact Server Support for assistance.</h2><br />");
            topWindow.write('<p style="color:red">' + message + "</p></body></html>");
            topWindow.close();
            return;
        }
    

    在主线中,您需要添加如下侦听器:

        google.maps.event.addDomListener(radarCircle,    'center_changed', reScope);
        google.maps.event.addDomListener(radarCircle,    'radius_changed', reScope);
        google.maps.event.addDomListener(radarRectangle, 'bounds_changed', reScope);
    
    
        function createFacilityMarkers(xmlhttp){
            facFinder = new Worker("facfinder.js");
            facFinder.addEventListener('message', workerInit, false);
    
            facFinder.postMessage({'cmd' : 'init', 'load' : xmlhttp.responseText});
         }
    
        function reScope() {
    
        var searchReq = {'cmd':'search', 'scopeVintage':scopeVintage};
        if (radarShape.getCenter) {
            searchReq.checker = 0;
            var currCenter = radarCircle.getCenter();
            searchReq.centerLat = currCenter.lat();
            searchReq.centerLng = currCenter.lng();         
            searchReq.radius = radarCircle.getRadius();
        } else {
            searchReq.checker = 1;
            searchReq.SWLat = radarShape.getBounds().getSouthWest().lat();
            searchReq.SWLng = radarShape.getBounds().getSouthWest().lng();
            searchReq.NELat = radarShape.getBounds().getNorthEast().lat();
            searchReq.NELng = radarShape.getBounds().getNorthEast().lng();
        }
    
        facFinder.postMessage(searchReq);
    }
    

    高温高压

    欢呼李察