Skip to content

Latest commit

 

History

History
363 lines (275 loc) · 17.5 KB

File metadata and controls

363 lines (275 loc) · 17.5 KB

七、识别和查找特征

能够识别特征并找到关于它们的信息是网络地图应用中的一个常见要求。在本章中,我们将介绍两个与返回特征属性相关的 ArcGIS Server 任务:IdentifyTaskFindTask

IdentifyTask返回地图上已点击的特征的属性。属性信息通常显示在弹出窗口中。与我们已经看到的其他任务一样,IdentifyTask对象依赖于输入参数,在本例中是一个名为IdentifyParameters的对象,它控制识别操作的结果。这些参数包括服务中用于识别操作的图层,以及被视为与地图点击位置相关的特征的可接受距离。IdentifyResult的一个实例用于保存任务的结果。 您可以使用 ArcGIS for JavaScript API 执行的任务通常会复制 ArcGIS Desktop 中一些最常用的功能。FindTask就是这样一个操作。就像在 ArcGIS 的桌面版本中一样,此任务可用于查找图层中与字符串值匹配的特征。在使用FindTask对象执行查找操作之前,您需要在FindParameters实例中设置操作的各种参数。FindParameters允许您指定搜索文本、搜索该文本的字段等内容。一旦提供了一个FindParameters对象,FindTask随后针对一个或多个层和字段执行其任务,并返回一个包含与搜索字符串匹配的layerIDlayerName和特征的FindResult对象。

在本章中,我们将讨论以下主题:

  • 使用IdentifyTask访问特征属性
  • 使用FindTask访问特征属性

使用标识任务访问特征属性

IdentifyTask允许用户点击地图并返回他们点击的一个或多个特征的信息。在本节中,您将学习如何使用与IdentifyTask相关联的各种对象来实现这一点。

介绍识别任务

与 ArcGIS Server 中的其他任务一样,IdentifyTask功能在 API 中分为三个不同的类:IdentifyParametersIdentifyTaskIdentifyResult。下图说明了这三个类:

识别参数

IdentifyTask的输入参数对象为IdentifyParameters。此对象包含许多属性,您可以使用这些属性来指定识别操作的参数。这些参数包括用于选择特征的几何图形(IdentifyParameters.geometry)、要在其上执行识别的图层(IdentifyParameters.layerIds)以及一个公差因子,该因子指定了要在结果中计数的特征与地图点击位置的距离(IdentifyParameters.tolerance)。

要使用 API 的识别功能,首先需要将IdentifyTaskIdentifyParametersIdentifyResults模块导入到您的应用中:

require(["esri/tasks/IdentifyTask", ... ], function(IdentifyTask, ... ){ ... }); 

IdentifyParameters对象上设置各种参数之前,您需要首先创建该对象的一个实例:

var identifyParams = new IdentifyParameters(); 

现在您有了一个IdentifyParameters的实例,您可以设置它的属性,如下所示:

identifyParams.geometry = evt.MapPoint;  identifyParams.layerIds[0,1,2];  
identifyParams.returnGeometry = true; identifyParams.tolerance = 3;  

在大多数情况下,使用用户在地图上点击的点来执行识别操作。您可以使用从地图点击事件返回的点来获得这一点,如前面的代码示例所示。应该搜索的图层可以使用传递到IdentifyParameters.layerIds属性的图层 id 数组来定义。数组应该包含引用要搜索的图层索引号的数值。您可以从服务目录中获取此信息。tolerance属性尤其重要。这将设置用于识别操作的几何体周围的像素距离。该几何图形通常是一个点,因此您可以将公差视为围绕该点的圆形缓冲区,其半径等于您指定的公差值(以屏幕像素为单位)。执行IdentifyTask时,将返回位于圆内或与圆相交的待识别图层的任何特征。

您可能需要试验这个容差值,以获得最适合您的应用的值。如果该值设置得太低,您将面临identify操作无法识别任何特征的风险,相反,如果该值设置得太高,您可能会返回太多特征。很难找到正确的平衡,适用于一种应用的公差值可能不适用于另一种应用。

标识任务

IdentifyTask使用IdentifyParameters中指定的参数在一个或多个图层上执行identify操作。和我们已经检查过的其他任务一样,IdentifyTask需要一个指向地图服务的网址的引用,以便在identify操作中使用。

可以使用下面的代码示例创建IdentifyTask的新实例。IdentifyTask构造函数只接受一个参数:包含将对其执行identify操作的图层的地图服务的网址;

var identify = new IdentifyTask("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer"); 

一旦创建了IdentifyTask对象的新实例,就可以调用IdentifyTask.execute()方法,该方法接受一个IdentifyParameters对象以及可选的成功回调和错误回调函数。

以下代码是调用IdentifyTask.execute()方法的示例。IdentifyParameters的一个实例作为一个参数传递到IdentifyTask.execute()方法中,同时引用一个addToMap()回调函数,该函数处理返回给它的结果:

identifyParams = new IdentifyParameters(); 
identifyParams.tolerance = 3; 
identifyParams.returnGeometry = true; 
identifyParams.layerIds = [0,2]; 
identifyParams.geometry = evt.mapPoint; 

identifyTask.execute(identifyParams, function(idResults) { addToMap(idResults, evt); }); 

function addToMap(idResults, evt) { 
    //add the results to the map 
} 

识别结果

IdentifyTask操作将一组IdentifyResult对象返回到成功callback功能。每个IdentifyResult对象包含由识别操作返回的特征以及发现该特征的图层 id 和图层名称。下面的代码说明了如何处理一组IdentifyResult对象:

function addToMap(idResults, evt) { 
bldgResults = {displayFieldName:null,features:[]}; 
parcelResults = {displayFieldName:null,features:[]}; 

for (vari=0, i<idResults.length; i++) { 
var idResult = idResults[i]; 
if (idResult.layerId === 0) { 
if (!bldgResults.displayFieldName) {bldgResults.displayFieldName = idResult.displayFieldName}; 
bldgResults.features.push(idResult.feature); 
          } 
else if (idResult.layerId === 2) { 
if (!parcelResults.displayFieldName) {parcelResults.displayFieldName = idResult.displayFieldName}; 
parcelResults.features.push(idResult.feature); 
          } 
        } 
dijit.byId("bldgTab").setContent(layerTabContent(bldgResults,"bldgResults")); 
dijit.byId("parcelTab").setContent(layerTabContent(parcelResults,"parcelResults")); 

map.infoWindow.show(evt.screenPoint, map.getInfoWindowAnchor(evt.screenPoint)); 
} 

练习时间-实现识别功能

在本练习中,您将在应用中实现识别功能。这是一个简单的应用,当用户单击地图时,会在信息窗口中显示建筑物和地块的属性信息。

按照给定的步骤完成练习:

  1. 打开https://developers . ArcGIS . com/JavaScript/3/sandbox/sandbox . html处的 JavaScript 沙盒。
  2. 从我突出显示的<script>标签中删除 JavaScript 内容,如下所示:
<script> 
  var map; 

  require(["esri/map", "dojo/domReady!"], function(Map) { 
    map = new Map("map", { 
      basemap: "topo",  //For full list of ... 
      center: [-122.45, 37.75], // longitude, latitude 
      zoom: 13 
    }); 
  }); 
</script>  
  1. 创建将在应用中使用的变量:
<script> 
   var map; 
   var identifyTask, identifyParams;    
</script>
  1. 创建require()函数,定义您将在此应用中使用的资源:
<script> 
  var map; 
  var identifyTask, identifyParams; 
  require([ 
  "esri/map", "esri/dijit/Popup", 
  "esri/layers/ArcGISDynamicMapServiceLayer", 
  "esri/tasks/IdentifyTask",  
  "esri/tasks/IdentifyResult",  
  "esri/tasks/IdentifyParameters", 
  "esri/dijit/InfoWindow",  
  "esri/symbols/SimpleFillSymbol", 
  "esri/symbols/SimpleLineSymbol", 
  "esri/InfoTemplate", "esri/Color", 
  "dojo/on", "dojo/domReady!" 
  ], function (Map, Popup, ArcGISDynamicMapServiceLayer,  
  IdentifyTask, IdentifyResult, IdentifyParameters, 
  InfoWindow, SimpleFillSymbol, SimpleLineSymbol, 
  InfoTemplate, Color, on) { 

  }); 
</script> 
  1. 创建Map对象的新实例,并将其与Popup相关联:
<script> 
  var map; 
  var identifyTask, identifyParams; 
  require([ 
  "esri/map", "esri/dijit/Popup", 
  "esri/layers/ArcGISDynamicMapServiceLayer", 
  "esri/tasks/IdentifyTask", 
  "esri/tasks/IdentifyResult", 
  "esri/tasks/IdentifyParameters", 
  "esri/dijit/InfoWindow", 
  "esri/symbols/SimpleFillSymbol", 
  "esri/symbols/SimpleLineSymbol", 
  "esri/InfoTemplate", "esri/Color", 
  "dojo/on", "dojo/domReady!" 
  ], function (Map, Popup, ArcGISDynamicMapServiceLayer, 
  IdentifyTask, IdentifyResult, IdentifyParameters, InfoWindow, 
  SimpleFillSymbol, SimpleLineSymbol, InfoTemplate, Color, on) { 
    //setup the popup window  
    var popup = new Popup({ 
      fillSymbol:  
      new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID, 
      new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, 
      new Color([255, 0, 0]), 2), 
      new Color([255, 255, 0, 0.25])) 
    }, dojo.create("div")); 

    // create the map 
    map = new Map("map", { 
      basemap: "streets", 
      center: [-83.275, 42.573], 
      zoom: 18, 
      infoWindow: popup 
    }); 

  }); 
</script> 
  1. 创建新的动态地图服务图层并将其添加到地图中:
// create the map 
map = new Map("map", { 
    basemap: "streets", 
    center: [-83.275, 42.573], 
    zoom: 18, 
    infoWindow: popup 
}); 

var landBaseLayer = new 
ArcGISDynamicMapServiceLayer(
"http://sampleserver3.arcgisonline.com
/ArcGIS/rest/services/
BloomfieldHillsMichigan/Parcels/MapServer",
{opacity:.55}); 
map.addLayer(landBaseLayer); 

});
  1. 添加一个Map.click事件,该事件将触发一个名为executeIdentifyTask的回调函数,当点击地图时,该函数将做出响应:
// create the map
map = new Map("map", {
basemap: "streets",
center: [-83.275, 42.573],
zoom: 18,
infoWindow: popup
});
var landBaseLayer = new ArcGISDynamicMapServiceLayer("http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/BloomfieldHillsMichigan/Parcels/MapServer",{opacity:.55});
map.addLayer(landBaseLayer);
map.on("click", executeIdentifyTask);
  1. 创建一个IdentifyTask对象:
identifyTask = new IdentifyTask("http://sampleserver3.arcgisonline.com/ArcGIS/
 rest/services/BloomfieldHillsMichigan/Parcels/MapServer");
  1. 创建一个IdentifyParameters对象,并设置代码中所示的属性,如下所示:
identifyTask = new IdentifyTask("http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/BloomfieldHillsMichigan/Parcels/MapServer"); 

identifyParams = new IdentifyParameters(); 
identifyParams.tolerance = 3; 
identifyParams.returnGeometry = true; 
identifyParams.layerIds = [0,2]; 
identifyParams.layerOption = IdentifyParameters.LAYER_OPTION_ALL; 
identifyParams.width  =map.width; 
identifyParams.height = map.height;
  1. 创建executeIdentifyTask()函数,它是Map.click事件的回调函数。executeIdentifyTask()函数接受一个参数,它是Event对象的一个实例。每个事件生成一个Event对象,该对象具有各种属性。在Map.click事件的情况下,该Event对象具有包含被点击的点的属性。这可以通过Event.mapPoint属性检索,并用于设置IdentifyParameters.geometry属性。IdentifyTask.execute()方法也返回一个Deferred对象。然后向这个分析结果的Deferred对象添加一个callback函数。添加以下代码创建executeIdentifyTask()功能。将其置于require()功能的之外:
function executeIdentifyTask(evt) {
  identifyParams.geometry = evt.mapPoint;
  identifyParams.mapExtent = map.extent;
  var deferred = identifyTask.execute(identifyParams);
  deferred.addCallback(function (response) {
    // response is an array of identify result objects
    // Let's return an array of features.
    return dojo.map(response, function (result) {
      var feature = result.feature;
      feature.attributes.layerName = result.layerName;
        if (result.layerName === 'Tax Parcels') {
          var template = new InfoTemplate("", "${Postal 
          Address} <br/> Owner of record: ${First Owner Name}");
          feature.setInfoTemplate(template);
        }
        else if (result.layerName === 'Building Footprints') {
          var template = new InfoTemplate("", "Parcel ID: 
          ${PARCELID}");
          feature.setInfoTemplate(template);
        }
        return feature;
      });
    });
  map.infoWindow.setFeatures([deferred]);
  map.infoWindow.show(evt.mapPoint);
} 
  1. 您可能需要查看示例代码的Chapter7文件夹中的解决方案文件(identify.html),以验证您的代码是否已正确编写。

  2. Execute the code by clicking the Run button and you should see the following output:

![](img/00082.jpeg)

使用查找任务访问特征属性

您可以使用FindTask在 ArcGIS Server REST 应用编程接口公开的地图服务中搜索字符串值。搜索可以在单个层的单个字段上进行,也可以在一个层的多个字段上进行,或者在多个层的多个字段上进行。与我们已经检查过的其他任务一样,查找操作依赖于互补的对象:FindParametersFindTaskFindResultFindParameters作为输入参数对象,FindTask用来完成其工作,FindResult包含任务返回的结果。

FindParameters

FindParameters用于指定查找操作的搜索标准,包括一个searchText属性,即要搜索的文本,以及指定要搜索的字段和图层的属性。此外,将returnGeometry属性设置为true表示您想要返回与查找操作匹配的特征的几何图形,这可用于突出显示地图上的结果。

下面的代码示例显示了如何创建FindParameters的新实例并为其属性赋值。在使用任何与查找操作相关的对象之前,您需要导入esri/tasks/FindTaskesri/tasks/FindParameters模块。searchText属性在searchFields属性定义的字段中定义要搜索的字符串值。将要搜索的图层定义在分配给layerIds属性的图层索引号数组中。索引号对应于地图服务中的图层。geometry属性定义是否应该在结果中返回特征几何。如果您不需要特征几何(也就是说,您不打算在地图上绘制或以其他方式参考几何),请将geometry属性设置为 false:

var findParams = new FindParameters(); 
findParams.searchText = dom.byId("ownerName").value; 
findParams.searchFields = ["LEGALDESC","ADDRESS"]; //fields to search 
findParams.returnGeometry = true; 
findParams.layerIds = [0]; //layers to use in the find 
findParams.outSpatialReference = map.spatialReference; 

您可以使用contains属性来确定是否查找搜索文本的精确匹配。如果contains为真,则搜索包含searchText属性中的字符串的值。这是不区分大小写的搜索。如果为假,则搜索searchText字符串的精确匹配。精确的匹配是区分大小写的。

查找任务

如下图所示,FindTaskFindParameters中指定的图层和字段执行查找操作,并返回包含满足查询的记录的FindResult对象:

findTask = new FindTask("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/TaxParcel/TaxParcelQuery/MapServer/"); 
findTask.execute(findParams,showResults); 

function showResults(results) { 
    //This function processes the results 
} 

QueryTask一样,您必须引用将在查找操作中使用的地图服务网址,但是您使用FindTask时,您引用的是整个地图服务,而不是地图服务中的特定图层,就像您对QueryTask所做的那样。查找操作将使用的地图服务中的图层和字段在FindParameters对象中定义。一旦实例化了FindTask,就可以调用其execute()方法,传入FindParameters对象作为第一个参数,还可以定义可选的成功和错误回调函数。这在前面的代码示例中进行了说明。成功回调函数被传递给包含find操作结果的FindResult,实例。

查找结果

FindResult包含FindTask操作的结果,包括关联特征(可用于将结果添加到地图的图形对象)、特征所属的图层标识和名称,以及包含搜索字符串的字段名称:

function showResults(results) { 
        //This function works with an array of FindResult that the task returns 
map.graphics.clear(); 
var symbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([98,194,204]), 2), new Color([98,194,204,0.5])); 

        //create array of attributes 
var items = array.map(results,function(result){ 
var graphic = result.feature; 
graphic.setSymbol(symbol); 
map.graphics.add(graphic); 
return result.feature.attributes; 

}); 

检索到这些信息后,该由你来处理了!例如,您可能想要在道场DataGrid中显示属性数据,或者创建某种报告。

摘要

返回与特征关联的属性是地理信息系统中最常见的操作之一。ArcGIS Server 有两个任务可以对此提供帮助:IdentifyTaskFindTaskIdentifyTask用于返回已在地图上点击的特征的属性。FindTask也返回特征属性,但执行简单的属性查询。此查询可帮助您定位满足查询的指定字段中包含文本的特征。在下一章中,您将学习如何通过使用地理编码来定位与地址相关联的特征。