能够识别特征并找到关于它们的信息是网络地图应用中的一个常见要求。在本章中,我们将介绍两个与返回特征属性相关的 ArcGIS Server 任务:IdentifyTask
和FindTask
。
IdentifyTask
返回地图上已点击的特征的属性。属性信息通常显示在弹出窗口中。与我们已经看到的其他任务一样,IdentifyTask
对象依赖于输入参数,在本例中是一个名为IdentifyParameters
的对象,它控制识别操作的结果。这些参数包括服务中用于识别操作的图层,以及被视为与地图点击位置相关的特征的可接受距离。IdentifyResult
的一个实例用于保存任务的结果。
您可以使用 ArcGIS for JavaScript API 执行的任务通常会复制 ArcGIS Desktop 中一些最常用的功能。FindTask
就是这样一个操作。就像在 ArcGIS 的桌面版本中一样,此任务可用于查找图层中与字符串值匹配的特征。在使用FindTask
对象执行查找操作之前,您需要在FindParameters
实例中设置操作的各种参数。FindParameters
允许您指定搜索文本、搜索该文本的字段等内容。一旦提供了一个FindParameters
对象,FindTask
随后针对一个或多个层和字段执行其任务,并返回一个包含与搜索字符串匹配的layerID
、layerName
和特征的FindResult
对象。
在本章中,我们将讨论以下主题:
- 使用
IdentifyTask
访问特征属性 - 使用
FindTask
访问特征属性
IdentifyTask
允许用户点击地图并返回他们点击的一个或多个特征的信息。在本节中,您将学习如何使用与IdentifyTask
相关联的各种对象来实现这一点。
与 ArcGIS Server 中的其他任务一样,IdentifyTask
功能在 API 中分为三个不同的类:IdentifyParameters
、IdentifyTask
和IdentifyResult
。下图说明了这三个类:
IdentifyTask
的输入参数对象为IdentifyParameters
。此对象包含许多属性,您可以使用这些属性来指定识别操作的参数。这些参数包括用于选择特征的几何图形(IdentifyParameters.geometry
)、要在其上执行识别的图层(IdentifyParameters.layerIds
)以及一个公差因子,该因子指定了要在结果中计数的特征与地图点击位置的距离(IdentifyParameters.tolerance
)。
要使用 API 的识别功能,首先需要将IdentifyTask
、IdentifyParameters
和IdentifyResults
模块导入到您的应用中:
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));
}
在本练习中,您将在应用中实现识别功能。这是一个简单的应用,当用户单击地图时,会在信息窗口中显示建筑物和地块的属性信息。
按照给定的步骤完成练习:
- 打开https://developers . ArcGIS . com/JavaScript/3/sandbox/sandbox . html处的 JavaScript 沙盒。
- 从我突出显示的
<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>
- 创建将在应用中使用的变量:
<script>
var map;
var identifyTask, identifyParams;
</script>
- 创建
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>
- 创建
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>
- 创建新的动态地图服务图层并将其添加到地图中:
// 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.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);
- 创建一个
IdentifyTask
对象:
identifyTask = new IdentifyTask("http://sampleserver3.arcgisonline.com/ArcGIS/
rest/services/BloomfieldHillsMichigan/Parcels/MapServer");
- 创建一个
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;
- 创建
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);
}
-
您可能需要查看示例代码的
Chapter7
文件夹中的解决方案文件(identify.html
),以验证您的代码是否已正确编写。 -
Execute the code by clicking the Run button and you should see the following output:
![](img/00082.jpeg)
您可以使用FindTask
在 ArcGIS Server REST 应用编程接口公开的地图服务中搜索字符串值。搜索可以在单个层的单个字段上进行,也可以在一个层的多个字段上进行,或者在多个层的多个字段上进行。与我们已经检查过的其他任务一样,查找操作依赖于互补的对象:FindParameters
、FindTask
和FindResult
。FindParameters
作为输入参数对象,FindTask
用来完成其工作,FindResult
包含任务返回的结果。
FindParameters
用于指定查找操作的搜索标准,包括一个searchText
属性,即要搜索的文本,以及指定要搜索的字段和图层的属性。此外,将returnGeometry
属性设置为true
表示您想要返回与查找操作匹配的特征的几何图形,这可用于突出显示地图上的结果。
下面的代码示例显示了如何创建FindParameters
的新实例并为其属性赋值。在使用任何与查找操作相关的对象之前,您需要导入esri/tasks/FindTask
和esri/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
字符串的精确匹配。精确的匹配是区分大小写的。
如下图所示,FindTask
对FindParameters
中指定的图层和字段执行查找操作,并返回包含满足查询的记录的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 有两个任务可以对此提供帮助:IdentifyTask
和FindTask
。IdentifyTask
用于返回已在地图上点击的特征的属性。FindTask
也返回特征属性,但执行简单的属性查询。此查询可帮助您定位满足查询的指定字段中包含文本的特征。在下一章中,您将学习如何通过使用地理编码来定位与地址相关联的特征。