Esri-Leaflet - 远距离搜索

     2023-02-23     247

关键词:

【中文标题】Esri-Leaflet - 远距离搜索【英文标题】:Esri-Leaflet - Search within a distance 【发布时间】:2021-03-16 15:45:52 【问题描述】:

我需要使用存储在 ArcGIS Online 中的要素图层来设计应用程序。使用地理编码器/搜索,我需要能够输入地址并选择距离(1 个街区、2 个街区等)。结果将显示新点、距离半径以及半径内的所有点。我还想要一个结果表。

我需要的与 DataMade 的 Derek Eder 创建的这个应用程序完全一样:https://carto-template.netlify.app/,除了我需要存储在安全 ArcGIS 图层中的数据。任何人都可以指出一个示例、教程等与此应用程序类似的 esri-leaflet 实现吗?在过去的五天里,我一直在尝试转换代码,但我觉得我无处可去。

这里是guthub的链接:https://github.com/datamade/searchable-map-template-carto

-------更新-------

Seth - 我可以让图层显示;但是,将搜索点与图层连接的查询不起作用。我想我遗漏了一些东西,因为控制台错误显示“需要令牌”。见下文:

    const radius = 1610;


    /**************************************************************************************************/
    // ArcGIS Authoization
    /**************************************************************************************************/

    $("#loginModal").modal( backdrop: 'static', keyboard: false );

    // submit element of form
    var submitBtn = document.getElementById('btnArcGISOnline');

    // add event listener to form
    submitBtn.addEventListener('click', addServicesFromServer);

    // create map and set zoom level and center coordinates
    var map = L.map('mapCanvas', 
    ).setView([30.46258, -91.13171], 12);

    // set basemap to Esri Streets
    L.esri.basemapLayer('Streets').addTo(map);

    var layerurl = 'secure/layer/URL';

    var tokenUrl = 'https://www.arcgis.com/sharing/generateToken';
    
    // function to make request to server
    function serverAuth(server, username, password, callback) 
        L.esri.post(server, 
            username: username,
            password: password,
            f: 'json',
            expiration: 86400,
            client: 'referer',
            referer: window.location.origin
        , callback);
    
    
    // function to run when form submitted
    function addServicesFromServer(e) 
        // prevent page from refreshing
        e.preventDefault();

        // get values from form
        var username = document.getElementById('username').value;
        var password = document.getElementById('password').value;

        // generate token from server and add service from callback function
        serverAuth(tokenUrl, username, password, function (error, response) 
            if (error) 
                return;
            

            // add layer to map
            var featureLayer = L.esri.featureLayer(
                url: layerurl,
                opacity: 1,
                token: response.token
            );
            featureLayer.addTo(map);
            $("#loginModal").modal("hide");

        ); // end serverAuth call
     // end addServicesFromServer call        

    // HARNESS GEOCODER RESULTS
    let circle;

    // GeoSearch
    const search = L.esri.Geocoding.geosearch(
        useMapBounds: false,
        expanded: true,
        collapseAfterResult: false
    );
    search.addTo(map);      
        
    search.on("results", (results) => 
        if (results && results.latlng) 
            if (circle) 
                circle.remove();
            
            circle = L.circle(results.latlng,  radius );
            circle.addTo(map);

            queryLayer(results.latlng);
        
    );

    // SET UP QUERY FUNCTION
    function queryLayer(point) 
        const query = L.esri.query( url: layerurl ).nearby(point, radius);
        query.run(function (error, featureCollection, response) 
            if (error) 
                console.log(error);
                return;
            
            console.log(featureCollection.features);
            populateList(featureCollection.features);
        );
    

    // WRITE RESULTS INTO A LIST
    function populateList(features) 
        const list = document.getElementById("results-list");
        let listItems = "";
        features.forEach((feature) => 
            listItems =
                listItems +
                `
                  <li>
                    Place: $feature.properties?.Location <br>
                    Lat: $feature.properties?.Latitude <br>
                    Lng: $feature.properties?.Longitude <br>
                  </li>
                `;

            list.innerHTML = listItems;
        );
    

我尝试将令牌传递给查询,如下所示,但随后出现无效令牌错误。

var layerUrl_token = layerurl + "?token=" + response.token;

我也尝试过使用 turf.js,但没有成功。我知道 turf.js 使用 long/lat,但我什至无法获得正确的语法来从要素层中提取 lat 和 long。

【问题讨论】:

【参考方案1】:

你想做的事情并不难。虽然有一些关于您想做的不同部分的教程,但让我们将它们拼凑起来。我将使用 esri-leaflet-geocoder 来实现我的搜索功能,因为它与 esri-leaflet 一致,并且 IMO 是可用于传单的最佳地理编码器之一。

设置地理编码器

设置基本的leaflet地图后,我们导入esri-leaflet和esri-leaflet-geocoder,并创建一个geocoder:

import L from "leaflet";
import * as EL from "esri-leaflet";
import * as ELG from "esri-leaflet-geocoder";

const search = ELG.geosearch(
  useMapBounds: false,
  expanded: true,
  collapseAfterResult: false
);

search.addTo(map);

不要忘记将地理编码器css添加到您的html中,如documentation example所示。

添加你的图层:

const layerurl = "YOUR_LAYER_URL";
const featureLayer = EL.featureLayer( url: layerurl );
featureLayer.addTo(map);

如果您使用需要身份验证的层,则需要获取一个令牌并将其用作功能层中的选项之一 (featureLayer( url: layerurl, token: token ))。如果您不确定如何获取令牌,请发表评论,我可以为此添加一些代码,但是已经有一些不错的教程可用。

利用搜索结果

ELG.geosearch 附带一个您可以利用的results 事件。当用户在地理搜索的自动完成下拉列表中选择结果之一时调用它。在那种情况下,我们可以获得用户选择的位置的位置数据。我们将地图居中(实际上是地理搜索的默认设置),用给定的半径画一个圆,然后执行查询(更多关于该图层):

let circle;

search.on("results", (results) => 
  if (results && results.latlng) 
    if (circle) 
      circle.remove();
    
    circle = L.circle(results.latlng,  radius );
    circle.addTo(map);

    queryLayer(results.latlng);
  
);

查询图层

现在我们知道用户从搜索中选择的位置的latlng。我们可以创建一个 esri-leaflet query,它可以通过各种方式查询您的要素图层。我们将看到一个nearby 查询,它将查询图层中给定点半径内的任何特征:

function queryLayer(point) 
  const query = EL.query( url: layerurl ).nearby(point, radius);
  query.run(function (error, featureCollection, response) 
    if (error) 
      console.log(error);
      return;
    
    populateList(featureCollection.features);
  );

如果您要查询经过身份验证的层,则需要在请求中添加令牌。我相当确定这样做的方法是这样的:

function queryLayer(point) 
  const query = EL.query( url: layerurl )
    .token(<your_token_here>)
    .nearby(point, radius);
  // ... same as above

您也可以直接在图层之外运行查询:

featureLayer.query().nearby(point, radius)

我对第二种方式不太熟悉,但您可以在这里阅读更多信息:Query a feature layer。

渲染到页面

一旦我们.run 查询,我们将能够以featureCollection 的形式访问结果。我们可以遍历该 featureCollection 的特性并渲​​染一些 HTML:

function populateList(features) 
  const list = document.getElementById("results-list");
  let listItems = "";
  features.forEach((feature) => 
    listItems =
      listItems +
      `
      <li>
        Place: $feature.properties?.Location <br>
        Lat: $feature.properties?.Latitude <br>
        Lng: $feature.properties?.Longitude <br>
      </li>
    `;

    list.innerHTML = listItems;
  );

在这个特定示例中,我使用的是我制作的点图层,该图层通过 arcgis online 提供服务。该点层没有地址数据,因此feature.properties 不包含任何地址信息。对于您的要素图层,您的图层属性将在feature.properties 中提供。因此,根据那里的内容,您可能想要使用feature.properties?.address 或其他什么。最后一点只是一个示例,您可能会根据自己的目的进行不同的自定义。

Working Codesandbox

在此示例中尝试搜索人口稠密的地区。请注意,在此要素图层中有许多重叠的位置,因此列表中的结果比地图上看起来的标记要多。

另外请注意,我使用 esri-leaflet 和 esri-leaflet-geocoder versions 2^ 发布此示例。这些在大约 1-2 个月前刚刚更新到版本 3,并且新版本需要在地理编码器和图层声明中使用 API 密钥,因此如果您想使用最新版本(推荐),您需要添加这些。我使用了版本 2,以免在沙箱中公开 API 密钥(我有点讨厌新的 API 密钥要求。新的 arcgis developers documentation for esri-leaflet 有一些例子,但官方文档 has not yet been updated匹配这些示例。

【讨论】:

赛斯 - 非常感谢!您提供的一切都按预期工作,但我在使用身份验证协议时遇到了问题。我用细节编辑了原始帖子。任何额外的帮助都会很棒。 我在答案的“查询图层”部分的末尾添加了一些额外的注释。您不必手动将 url 附加到令牌中,如果需要令牌,esri-leaflet 有一些内置方法可以将您的令牌包含在请求中。 救生员。非常感谢!!

esri-leaflet入门教程-自定义底图

esri-leaflet入门教程(3)-自定义底图by李远祥     在前面的篇章我们已经了解到了怎么样使用FlatUI、leaflet和esri-leaflet去搭建简单的地图应用界面了。如果有着手写代码的朋友可能已经发现第一个HelloWorld程序,使... 查看详情

esri-leaflet入门教程-动态要素加载

esri-leaflet入门教程(5)- 动态绘制图形by李远祥     在上一章节中已经说明了esr-leaflet是如何加载ArcGISServer提供的各种服务,这些都是服务本身来决定的,API脚本只是非常简单的调用。但如果要做一列的地图... 查看详情

esri-leaflet入门教程-加载各类图层

esri-leaflet入门教程(4)-加载各类图层by李远祥   在leaflet中图层一般分为底图(Basemap)和叠加图层(Overlay)。前面章节已经介绍过底图其实也是实现了TileLayer接口,而其他的叠加图层要么就是叠加的业务图层,要么... 查看详情

htmlkamp2016:agol,leaflet,esri-leaflet和turf(代码片段)

查看详情

esri-leaflet入门教程-动态绘制图形

esri-leaflet入门教程(5)-动态绘制图形by李远祥   在上一章节中已经说明了esr-leaflet是如何加载ArcGISServer提供的各种服务,这些都是服务本身来决定的,API脚本只是非常简单的调用。但如果要做一列的地图交互操... 查看详情

弹性搜索5.x中地理距离查询中的返回距离

】弹性搜索5.x中地理距离查询中的返回距离【英文标题】:Returndistanceingeodistancequeryinelasticsearch5.x【发布时间】:2017-06-0215:13:44【问题描述】:我需要使用地理距离查询从弹性搜索中的搜索坐标获取距离。我试过这个curl-XGET\'http:... 查看详情

用于距离搜索的 Mysql POINT 列

】用于距离搜索的MysqlPOINT列【英文标题】:MysqlPOINTcolumnfordistancesearch【发布时间】:2014-10-3112:51:50【问题描述】:是的,我知道这个问题曾经问过很多时间,但从2012年开始,一切似乎都已经过时了,这些问题/答案的基础,我尝... 查看详情

距离内的 Oracle 空间搜索

】距离内的Oracle空间搜索【英文标题】:Oraclespatialsearchwithindistance【发布时间】:2012-02-2202:57:15【问题描述】:我有下表城市:ID(int),City(char),latitude(float),longitude(float).现在根据用户的经度(例如:44.8)和纬度(例如:46.3)我想... 查看详情

在 Java 中使用 Levenshtein 距离改进搜索结果

】在Java中使用Levenshtein距离改进搜索结果【英文标题】:ImprovingsearchresultusingLevenshteindistanceinJava【发布时间】:2016-02-1618:35:15【问题描述】:我有以下工作Java代码,用于在单词列表中搜索单词,它可以完美地按预期工作:publiccl... 查看详情

快速方法按距离搜索数百万个坐标

】快速方法按距离搜索数百万个坐标【英文标题】:Fastwaysearchmillionsofcoordinatesbydistance【发布时间】:2018-10-3115:01:47【问题描述】:我有一个大约2000万坐标的数据集。我希望能够以英里为单位传递纬度、经度和距离,并返回在我... 查看详情

Laravel 5.2通过与用户邮政编码的距离搜索用户

】Laravel5.2通过与用户邮政编码的距离搜索用户【英文标题】:Laravel5.2searchforusersbydistancefromuserspostcode【发布时间】:2016-07-0709:54:42【问题描述】:我有一个关于Laravel5.2的问题并尝试按距离搜索用户。到目前为止,这是我的数据... 查看详情

查找二叉搜索树从根到特定键的距离

】查找二叉搜索树从根到特定键的距离【英文标题】:Findingthedistanceofabinarysearchtreefromtheroottoaspecifickey【发布时间】:2020-06-2712:52:05【问题描述】:defdistance(self,rootOfTree,key):ifrootOfTreeisNone:return-1totalDist=-1ifrootOfTree.keyiskey:returnto 查看详情

leetcode783.二叉搜索树结点最小距离(minimumdistancebetweenbstnodes)(代码片段)

783.二叉搜索树结点最小距离LeetCode783.MinimumDistanceBetweenBSTNodes题目描述给定一个二叉搜索树的根结点root,返回树中任意两节点的差的最小值。示例:输入:root=[4,2,6,1,3,null,null]输出:1解释:注意:root是树结点对象(TreeNodeobject),而不是数... 查看详情

数据库中的汉明距离/相似性搜索

】数据库中的汉明距离/相似性搜索【英文标题】:HammingDistance/Similaritysearchesinadatabase【发布时间】:2012-03-2506:38:37【问题描述】:我有一个过程,类似于生成感知哈希的tineye,这些是32位整数。我打算将来将这些存储在sql数据库... 查看详情

dijkstra算法,用于对有权图进行搜索,找出图中两点的最短距离

Dijkstra算法,用于对有权图进行搜索,找出图中两点的最短距离,既不是DFS搜索,也不是BFS搜索。 把Dijkstra算法应用于无权图,或者所有边的权都相等的图,Dijkstra算法等同于BFS搜索。http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/... 查看详情

如何根据坐标列表与当前位置的距离进行搜索并显示? (Windows 电话 7)

】如何根据坐标列表与当前位置的距离进行搜索并显示?(Windows电话7)【英文标题】:Howtosearchthroughalistofcoordinatesanddisplay,dependingonthedistancebetweenitandcurrentlocation?(WindowsPhone7)【发布时间】:2012-04-1115:37:50【问题描述】:我已经收... 查看详情

百度地图怎么测量两地的直线距离和行车距离

...内找到“地图”选项并单击。2、然后在弹出的界面内的搜索框内输入想要测量的两个地址,然后进行搜索。3、然后在界面内找到“工具箱”选项并单击,再在弹出的界面内找到“测距”选项并单击。4、最后将地图放大,再双击... 查看详情

783.二叉搜索树结点最小距离(代码片段)

给定一个二叉搜索树的根结点 root,返回树中任意两节点的差的最小值。示例:输入:root=[4,2,6,1,3,null,null]输出:1解释:注意,root是树结点对象(TreeNodeobject),而不是数组。给定的树[4,2,6,1,3,null,null]可表示为下图:4/26/13最小的差值是... 查看详情