当前位置: 首页 > 知识库问答 >
问题:

Esri传单-在一定距离内搜索

堵睿范
2023-03-14

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

我需要的是完全一样的这个应用程序创建德里克埃德尔从数据制造:https://carto-template.netlify.app/,除了我的需要的数据存储在一个安全的ArcGIS层。有人能给我指一个例子,教程等与类似于此应用程序的esri传单实现?在过去的五天里,我一直在尝试转换代码,但我觉得我一无所获。

以下是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;
        });
    }

我试图将令牌传递给下面粘贴的查询,但随后出现无效令牌错误。

VARlayerUrl_token=layerurl"?Token="response.token;

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

共有1个答案

叶嘉颖
2023-03-14

你想做的不是太难。虽然有一些关于你想做什么的不同部分的教程,但让我们把事情拼凑起来。我将使用esri传单地理编码器作为我的搜索功能,因为它与esri传单一致,IMO是传单中最好的地理编码器之一。

设置基本传单地图后,让我们导入esri传单和esri传单地理编码器,并创建地理编码器:

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);

不要忘记将geocoder css添加到html中,如文档示例所示。

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

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

ELG. geossearch附带了一个可以利用的结果事件。当用户在地理搜索的自动完成下拉列表中选择一个结果时,将调用它。在这种情况下,我们可以得到用户选择的位置的位置数据。我们将地图放在那里(这实际上是地理搜索的默认值),用给定的半径画一个圆,并执行查询(该层的更多内容):

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传单查询,它可以以各种方式查询您的特征层。我们将看到一个附近的查询,它将查询该层在一个点的给定半径内的任何特征:

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)

我对第二种方法不太熟悉,但您可以在这里了解更多信息:查询要素图层。

一旦我们. run查询,我们就可以以特性集合的形式访问结果。我们可以循环遍历该特性集合的特性,并呈现一些超文本标记语言

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;
  });
}

在这个特定的例子中,我使用了一个我制作的点图层,它通过argis在线提供服务。这个点层没有地址数据,所以feature.properties不包含任何地址信息。对于特征层,层的属性将在feature.properties中可用。所以根据那里有什么,你可能想使用feature.properties?.address或其他什么。最后一点只是一个例子,您可能会根据自己的目的对其进行不同的定制。

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

另外请注意,我使用esri传单和esri传单geocoder版本2^发布的示例。这些版本在大约1-2个月前刚刚更新到版本3,新版本要求在地理编码器和层声明中使用API密钥,因此如果您想使用最新版本(推荐),则需要在中添加这些API密钥。我使用版本2是为了不在沙箱中暴露API密钥(我有点讨厌新的API密钥要求。新的arcgis开发者esri文档传单中有一些例子,但官方文档尚未更新以匹配这些例子。

 类似资料:
  • 我正在研究一个图问题,其中给定了一个源节点,需要找到距离固定的所有其他节点,其中节点之间的每条边都有一个统一的代价。因此,我使用标准FIFO队列技术实现了广度优先搜索,但在固定距离停止BFS会给我带来问题。 如果我使用DFS,我可以在每次递归调用时传递当前深度,但是在这里我不能这样做。我也不能修改图中的节点来保留一个额外的参数(距离)。有什么建议或者参考吗?

  • 问题内容: 选项 询问 我有一个包含4列的数据库表: 唯一身份 城市名 纬度(纬度) 经度(lng) 我在顶部使用查询返回距指定坐标距离指定英里数内的位置。它似乎可行,但我不确定它的准确性如何。我很想知道查询是否很好,或者您是否有更好的解决方案。 问题答案: 看起来像是正确的大圆距查询。 您对WRT的准确性有何看法?

  • 给出一个2d点的列表和一个最大距离d,比O(n^2更好的方法是什么)找出哪些点位于每个点的d以内。我不需要解决方案,只需要一些开始的想法。

  • 更新时间:2018-09-15 11:02:51 功能说明 光和距离传感器。ltr553 是一款环境光和距离传感器,通过 I2C 进行数据交互。 硬件资源 DevelopKit 开发板上自带有 ltr553 传感器: 软件设计 根据 ltr553 的数据手册,ALS 有两个通道寄存器 0x8A、0x88,一般我们会同时读取两个通道的值,然后取其平均值,PS 值存放在寄存器 0x8D 中,直接读取就

  • 问题内容: 我有一个MySQL表(MyISAM),其中包含我根据与另一对经纬度对之间的距离(大圆公式)从中选择的约20万经纬度对条目。(例如,在50.281852,2.504883附近的10公里半径内的所有条目) 我的问题是此查询大约需要0.28秒。仅针对这200k条目运行(每天仍在增加)。而0.28秒。通常情况下会很好,此查询会经常运行,因为它会增强我的Web应用程序的主要功能,而且通常是较大查

  • 我需要计算汽车行驶的距离!不是距离,不是距离到否。如果我们通过谷歌提供的API计算,距离可以完全不同。谷歌可以提供从一个点到另一个点的1公里距离,但汽车可以按照骑手想要的方式行驶800米。使用加速计没有帮助。它适用于步行,但绝不适用于更快的速度。 我尝试过使用Google的位置API:距离到或距离之间根本不是一个选项。它可以给出与IN REAL截然不同的结果。在真实的汽车中,可以通过非常短的地方并