ArcGIS API for JavaScript 4.2学习笔记[22] 使用【QueryTask类】进行空间查询 / 弹窗样式

上一篇写道,使用Query类进行查询featureLayer图层的要素,也简单介绍了QueryTask类的使用。

这一篇博文继续推进,使用Query类和QueryTask类进行空间查询,查询USA的著名山体点要素。

同样的,只介绍重点。本章官方名字是:Query using QueryTask


 照常,先看看结果:(默认三个参数都不动,直接点击按钮)

出现了绿色的圆锥体,点击圆锥体可以出现定制好的弹窗(PopupTemplate):

好,开始上课。


 

给出引用 

require([
  "esri/Map",
  "esri/views/SceneView",
  "esri/layers/GraphicsLayer",
  "esri/symbols/PointSymbol3D",
  "esri/symbols/ObjectSymbol3DLayer",
  "esri/tasks/QueryTask",
  "esri/tasks/support/Query",
  "dojo/_base/array",
  "dojo/dom",
  "dojo/on",
  "dojo/domReady!"
  ], 
  function(
    Map, SceneView, GraphicsLayer, PointSymbol3D, 
    ObjectSymbol3DLayer, QueryTask, Query, arrayUtils, dom, on)
  {...}
)

GraphicsLayer是用于显示绿色的圆锥体的几何图层;

ObjectSymbol3DLayer、PointSymbol3D是用于显示绿色圆锥的模块;

Query和QueryTask是本节空间查询必须的模块。


给出骨架

function(...)
{
      var peaksUrl = ...(要素服务)
      var popupTemplate = {...};
      var mtnSymbol = new PointSymbol3D({...});
      var resultsLyr = new GraphicsLayer({...});

      //空间查询二要素
      var qTask = new QueryTask({...});
      var params = new Query({...});
      
      var map = new Map({...});
      var view = new SceneView({...});

      var attributeName = dom.byId("attSelect");
      var expressionSign = dom.byId("signSelect");
      var value = dom.byId("valSelect");

      //方法体
      function doQuery(){...}
      function getResult(response){...}
      function promiseRejected(err){...}

      //DOM按钮事件
      on(dom.byId("doBtn"), "click", doQuery);
}

为了节约篇幅与抓重点,从这儿开始就不再对Map类和View类的对象实例化进行代码展示了,我相信一路看过来我的博文的同学都能看懂那个基础的两个类的使用了。除非这两个类有新的属性赋值,否则均省略不写。

这例程序仍然有popupTemplate,作为绿色圆锥点状符号的查询结果弹出窗。惊奇的是我发现了可以通过CSS控制弹窗的部分样式:

.esri-popup .esri-popup-header .esri-title {
  font-size: 18px;
  font-weight: bolder;
}

.esri-popup .esri-popup-body .esri-popup-content {
  font-size: 14px;
}

使用的是.选择器。

简略看看弹窗模板的构成:(复习一下)

var popupTemplate = {
    title : "{...},{...}",
    fieldsInfos: [{...},{...},{...},{...},{...},{...}],
    content: "<b><a href='https://en.wikipedia.org/wiki/Topographic_prominence'>Prominence:</a>" +
    "</b> {PROMINENCE_ft} ft ({PROMINENCE_m} m)" +
    "<br><b>Prominence Rank:</b> {RANK}" +
    "<br><b>Elevation:</b> {ELEV_ft} ft ({ELEV_m} m)" +
    "<br><b><a href='https://en.wikipedia.org/wiki/Topographic_isolation'>Isolation:</a>" +
    "</b> {ISOLATION_mi} mi ({ISOLATION_km} km)"
};

title使用两个字段填充,拥有6个字段信息(fieldsInfos)作为content的填充内容;

content仍然是使用html语言的文本形式进行输出。

紧接着是符号和几何图层的定义:

var mtnSymbol = new PointSymbol3D({
  symbolLayers: [new ObjectSymbol3DLayer({
    resource: {
      primitive: "cone"
    }
  })]
});
var resultsLyr = new GraphicsLayer();

在这里要提及一下PointSymbol3D类,这个类是esri/Symbol下的一个模块,同等级的还有LineSymbol3D、MeshSymbol3D、PolygonSymbol3D等。

这里用了一个属性:symbolLayers,类别是ObjectSymbol3DLayer数组(Collection类型,所以这里给的形式是[]数组)。

在属性的赋值中直接new了ObjectSymbol3DLayer,ObjectSymbol3DLayer使用了resourse属性,它是一个Object类型的属性。这里给定值primitive属性是"cone"字符串,代表的意义就是圆锥。primitive是一个resource属性的属性,其是一个枚举值,见:点我

紧接着就是本文最重点的地方了!

空间查询二元素

上代码:

var qTask = new QueryTask({
  url: peaksUrl
});
var params = new Query({
  returnGeometry: true,
  outFields: ["*"]
});

Query见上篇博文,而这个QueryTask则需要好好解释一下了:

 

它是esri/tasks/目录下的一个模块,继承自Accessor的子类Task,是AJS4.x才有的。

它的出现,是为了满足在某一个图层上进行空间查询的需要。它最常用的方法就是excute()方法了,通常,需要传入一个Query对象。

它的返回类型是Promise的FeatureSet类的对象(有点拗口,Promise算是一个特征吧)

返回的FeatureSet是符合传入Query的在图层上的所有要素的集合。

本例中,使用了要素服务作为QueryTask的构造器:

var qTask = new QueryTask({
  url: peaksUrl
});

url这个属性见下:

它可以是FeatureServer,也可以是MapServer。也就是说我们可以使用Server上的这两种服务来实例化一个QueryTask对象。

好,空间分析二元素就创建好了,有了Query对象和QueryTask对象,我们就需要进行空间搜索了,既然巧妇难为无米之炊,现在有了米,也该炊起来了。

分析部分

我先上个图,会比代码看起来更有立体感:

当按下DOM上的按钮时,触发doQuery事件,此时从三个下拉框中获取参数(即option标签的value值),设置成SQL查询语句,即Query对象的where属性。

此时,把Query对象(名为param)传入QueryTask对象(名为qTask)的excute()方法内,使用getResults()方法作为成功查询的回调函数,使用promiseRejected()方法作为查询失败的回调函数。

逻辑很简单,只有一个分支,失败的promiseRejected()就不细说了,只是在后台控制台输出错误信息而已。

主要看getResults,看看它对查询结果做了什么:

function getResults(response) {
  var peakResults = arrayUtils.map(response.features, function(feature) {
feature.symbol = new PointSymbol3D({...}); feature.popupTemplate
= popupTemplate; return feature; }); resultsLyr.addMany(peakResults); view.goTo(peakResults); dom.byId("printResults").innerHTML = peakResults.length + " results found!"; }

response就是FeatureSet对象了吧,对其features对象使用一个方法体function(feature){...}来操作每一个feature:

首先,设置symbol属性,就是图中绿色的小圆锥体;

其次,设置的是popupTemplate属性,就是弹窗,在本篇上面有介绍。

最后返回feature,作为peakResults数组的一个元素。

这个peakResults数组就是搜索得到的要素的集合,只不过添加了弹窗模板和圆锥点状符号而已~

在这里,使用到了arrayUtils这个类的map方法,遍历操作了features的每一个feature。

【经过查询,arrayUtils查不到信息,dojo官方网站给的是array.map()方法,可能这两个是版本区别吧...?】

 

关于PointSymbol3D({...})这里面的内容我不多叙述了,给出源代码,各位对符号有兴趣可以自行学习。

feature.symbol = new PointSymbol3D({
  symbolLayers: [new ObjectSymbol3DLayer({
    material: {
      color: "green"
    },
    resource: {
      primitive: "cone"
    },
    width: 100000,
    height: feature.attributes.ELEV_m * 100
  })]
});
PointSymbol3D

peakResults作为Object数组传入resultLyr,然后将视图定位到peakResults(使用goTo()动画),并刷新DOM上的文字信息,提示有多少个点被找到。

总结一下

这个例子,我没记错的话是第一个接触到Task这个类的东西,这里是Task类的子类QueryTask。

思路比较简单,把Query对象传入QueryTask对象,再由回调函数处理返回的FeatureSet即可。

这里还用到了简单的3D点符号~

【最后叹一句:终于能恢复更新了,估计这周内就能完成空间查询和空间分析章节的笔记!】

posted @ 2017-04-07 16:21  岭南灯火  阅读(5977)  评论(1编辑  收藏  举报