ArcGIS API for JavaScript 4.2学习笔记[20] 使用参数查询要素(油井和地震关系)

这个例子相当复杂。我先简单说说这个例子是干啥的。

在UI上,提供了一个下拉框、两个滑动杆,以确定三个参数,使用这三个参数进行空间查询。这个例子就颇带空间查询的意思了。

这个例子是干嘛的呢?第一个参数是油井类型,第二个参数是油井的缓冲半径,第三个参数是地震级别。

给定油井的类型,给定油井的缓冲半径,给定地震级别,就能在油井附近以这个缓冲半径为圆搜索出符合给定地震级别的地震数据。

因为开采油田会导致地下空间坍塌,而引发地震。



看看搜索结果(随便选的参数):

橙色点即为搜索结果(地震点)。



给出引用

话不多说,看看这个例子的引用有多少:

require(
    [
        "esri/Map",
        "esri/views/MapView",
        "esri/layers/FeatureLayer",
        "esri/layers/GraphicsLayer",
        "esri/geometry/geometryEngine",
        "esri/Graphic",
        "esri/symbols/SimpleFillSymbol",
        "esri/symbols/SimpleMarkerSymbol",

        "dojo/on",
        "dojo/dom",
        "dojo/dom-construct",
        "dojo/domReady!"
    ],
    function(...){...}
);

用到了两种Layer,FeatureLayer是数据图层,GraphicsLayer是缓冲区图层和结果显示图层。

为了支持GraphicsLayer的缓冲区,需要用到geometryEngine模块和Graphics模块。

为了支持结果显示,用到了SimpleFillSymbol模块和SimpleMarkerSymbol模块。

函数参数骨架

function(Map, MapView, FeatureLayer, GraphicsLayer, Graphics, SimpleFillSymbol, SimpleMarkerSymbol)
{
    var quakesUrl = "...";
    var wellBuffer,wellsGeometries,magnitude;

    //获取dom元素
    var wellTypeSelect = dom.byId("well-type");
    var magSlider = dom.byId("mag");
    var distanceSlider = dom.byId("distance");

    //FeatureLayer&GraphicsLayer定义
    var wellsLayer = new FeatureLayer({...});
    var quakesLayer = new FeatureLayer({...});
    var resultsLayer = new GraphicsLayer({...});

    var map = new Map({...});
    var view = new MapView({...});
    view.ui.add("infoDiv", "top-right");
    view.then(function(){...});

    //功能方法
    function getValues(response){...}
    function getUniqueValues(values){...}
    function addToSelect(values){...}
    function setWellsDefinitionExpression(newValue){...}
    function queryForWellGeometries(){...}
    function createBuffer(wellPoints){...}

    //事件
    on(magSlider, "input", function(){...});
    on(distanceSlider, "input", function(){...});
    on(distanceSlider, "change", function(){...});
    on(wellTypeSelect, "change", function(evt){...});
    on(dom.byId("query-quakes"), "click", function(){...});

    //其余方法
    function queryEarthquakes(){...}
    function displayResults(results){...}
)

函数参数骨架

可吓坏我了,这么庞大的骨架(script标签就有200+行)。

经过我一个月的细读,我终于把这些流程大概弄懂了,如下图:

有些地方表述可能不太对。

分为两块,一块是事件体,另一块是函数体。

先讲简单的吧,事件体。

事件体

wellTypeSelect和distanceSlider这两个dom元素的change事件体都会独立触发createBuffer()函数体,wellTypeSelect事件则会先触发setWellsDefinitionExpression()函数体进行遍历搜索几何体,然后把返回值(地震点的几何体集合wellsGeometries)交给createBuffer()函数体,生成缓冲区。

意思是只要油井类型(下拉列表的项目改变)和距离滑块改变,缓冲区就要进行重绘。

distanceSlider的input事件会改变DOM上的数值,为缓冲区半径的数值。

magSlider的input事件会改变DOM上的数值,为地震级别的数值。

queryQuakes按钮的click事件会通过已经生成的缓冲区进行叠置分析,搜索缓冲区内的地震点。

对大量的变量如果不是很懂,这里可以先缓缓,下面的函数体会更详细介绍,事件体主要明白DOM的事件能干啥就行了。

函数体

有几个函数体是连锁反应的,而且是在MapView的then中进行连锁异步操作的。

在这里我又不得不提一下异步操作和这个then的用法了。

then的含义就是,等then前面的操作在服务器上做完后,再执行then里面的内容。

因为js是单线程的解释型语言,不会编译,只会从头到尾一次读下来,所以执行到then前面的代码时,是不可能停在那里的

then前面的代码执行完肯定有一个类似回执的东西(可以理解为返回值),但是浏览器不能一直等待这个回执啊?

所以就在then里面写一个回调函数,丢给服务器,在服务器端等待then前的操作完成后,再把“返回值”返还给回调函数做,即可。

then()里的东西不会立刻在本地执行,在本地等待前一步的操作结果只会让浏览器卡死。

实际上,我标红的关键词,就是异步操作的思想了。

复习完异步操作和then,我们再看看view的那一串then:

view.then(function() {
    return wellsLayer.then(function() {
      var query = wellsLayer.createQuery();
      return wellsLayer.queryFeatures(query);
    });
  })
  .then(getValues)
  .then(getUniqueValues)
  .then(addToSelect)
  .then(createBuffer);

我直接给出我的解读:首先,view加载完后,执行第一个then,第一个then返回wellsLayer的空间搜索(queryFeatures()这个方法)结果,这个结果是FeatureSet类型的,名为response。这response在哪用呢?它传递给了getValues()这个方法体:

function getValues(response) {
  var features = response.features;
  var values = features.map(function(feature) {
    return feature.attributes.STATUS2;
  });
  return values;
}

经查,response确实就是FeatureSet类的实例,通过getValues获取其内所有features的所有STATUS2字段的值,名为values,类型为AJS中的Collection类型。

values又传递给getUniqueValues()方法体:

function getUniqueValues(values) {
  var uniqueValues = [];
  values.forEach(function(item, i) {
    if ((uniqueValues.length < 1 || uniqueValues.indexOf(item)===-1) && (item !== "")) {
      uniqueValues.push(item);
    }
  });
  return uniqueValues;
}

根据某些规则(if语句)遍历values,使用Collection类的forEach方法,然后把遍历结果作为JS的数组返回,名为uniqueValues,传递给

addToSelect()方法体,实现选择列表这个DOM元素上出现油井类型(option):

function addToSelect(values) {
  values.sort();//排序
  values.forEach(function(value) {
    var option = domConstruct.create("option");
    option.text = value;
    wellTypeSelect.add(option);//给下拉列表添加选项  return setWellsDefinitionExpression(wellTypeSelect.value);
});

不能光添加呀!所以它就return了,方法setWellsDefinitionExpression()的结果。

setWellsDefinitionExpression()这个方法是设置wellsLayer的SQL查询语句的,但是没完,setWellsDefinitionExpression()这个方法内还有一层return:

function setWellsDefinitionExpression(newValue) {
  wellsLayer.definitionExpression = "STATUS2 = ‘" + newValue + "‘";
  if (!wellsLayer.visible) {
    wellsLayer.visible = true;
  }
  return queryForWellGeometries();
}

function queryForWellGeometries() {
  var wellsQuery = wellsLayer.createQuery();
  return wellsLayer.queryFeatures(wellsQuery)
    .then(function(response) {
      wellsGeometries = response.features.map(function(feature) {
        return feature.geometry;//返回某个要素的几何体
      });
      return wellsGeometries;//返回所有的几何体(作为集合)
    });
}

queryForWellGeometries()这个方法是setWellsDefinitionExpression()这个方法必定会触发的方法体,它用于搜索wellsLayer中的几何体。

空间查询要点

注意到了吗?空间查询是需要某个Layer的query对象的。

在wellsLayer中,使用createQuery()方法就能返回一个query对象,query对象包含了所有用于空间查询(搜索)用的信息,通过它,才能使用queryFeatures等方法对需要进行空间查询(搜索)的图层进行空间查询(搜索)。

所以图中的连串的then对应的方法体就已经解释完毕了。(呼呼~不知道各位能不能坚持到这,也不知道各位能不能看懂...)

还剩三个方法体,createBuffer()、queryEarthQuakes()和displayResults()方法体。

先来看看createBuffer():

function createBuffer(wellPoints) {
  var bufferDistance = parseInt(distanceSlider.value);
  var wellBuffers = geometryEngine.geodesicBuffer(wellPoints, [
      bufferDistance
    ], "meters",
    true);
  wellBuffer = wellBuffers[0];
  var bufferGraphic = new Graphic({
    geometry: wellBuffer,
    symbol: new SimpleFillSymbol({
      outline: {
        width: 1.5,
        color: [255, 128, 0, 0.5]
      },
      style: "none"
    })
 });

  view.graphics.removeAll();
  view.graphics.add(bufferGraphic);
}

从DOM元素中获取缓冲区半径,然后用geometryEngine这个工具集(或者叫类,还没到空间分析章节就不说那么多了)中的geodesicBuffer方法产生缓冲区,数据是传入的参数wellPoints,即上面addToSelect()方法中最后一层返回的几何体集合(油井点集合)。

然后实例化Graphic实例,设置颜色、线宽,然后添加到view中的graphics容器内即可。

再看queryEarthQuakes()和displayResults():

function queryEarthquakes() {
  var query = quakesLayer.createQuery();
  query.where = "mag >= " + magSlider.value;
  query.geometry = wellBuffer;
  query.spatialRelationship = "intersects";

  return quakesLayer.queryFeatures(query);
}
function displayResults(results) {
  resultsLayer.removeAll();
  var features = results.features.map(function(graphic) {
    graphic.symbol = new SimpleMarkerSymbol({
      style: "diamond",
      size: 6.5,
      color: "darkorange"
    });
    return graphic;
  });
  var numQuakes = features.length;
  dom.byId("results").innerHTML = numQuakes + " earthquakes found";
  resultsLayer.addMany(features);
}

前一个设置query(又是query!)的信息,返回quakesLayer搜索的结果(看下一个方法,应该是FeatureSet类型的),结果传递给displayResults(在按钮的click事件中通过then异步传递),名为results。

在后一个方法体中,使用map方法遍历要素中所有几何体,设置线宽和色彩等符号样式,最后在DOM元素上刷新显示搜索得到了多少个地震点“numQuakes earthquakes found”,并在结果图层中添加这些要素,刷新显示。

最后两个其实就是通过上方生成的缓冲区进行空间查询(搜索),得到结果并刷新显示的过程。



至此,本例就全部解释完毕了,至于有些变量是什么,看new的类型就知道啦,一路看我的文章应该都懂的。

————

感言:一个月了,好拖啊...4.3都出了这么久了,才把这个例子攻克。嗯,接下来的例子就不会那么又臭又长了...

总结一下

本例通过对图层的query对象的使用,以及结合空间分析中的缓冲区(使用geometryEngine),进一步加深了异步操作和遍历的代码理解。

要说能符合本章空间查询(搜索)的核心代码,也不过是wellsLayer.createQuery()这一句代码和query对象的属性设置了,Graphics的操作(遍历、属性设置)和结果的互相传递都不是本章的重点,所以导致了这个例子阅读困难。

大致流程为:从featureLayer中获取字段值,并加到下拉选择列表中——选择某个油井类型,设置缓冲半径,后台获取油井的点几何体集合,生成缓冲区——使用缓冲区,和设置好的地震级别,进行空间查询,得到地震点的搜索结果,刷新显示。

over!

时间: 2024-10-06 22:37:43

ArcGIS API for JavaScript 4.2学习笔记[20] 使用参数查询要素(油井和地震关系)的相关文章

ArcGIS API for JavaScript 4.2学习笔记[30] 点和线高程查询(第八章完结)

终于到最后一篇了,可喜可贺. 本例先说明了如何进行单点的高程差分析,然后说明了道路的起伏分析.前者很直观地比较了两个年份的高程数据之间的差值,体现山区的高程变化(有啥用啊?)后者,一条路上的起点终点起伏多少,可以给驾驶导航提供更多样化的数据. 本例使用了高程图层和RouteTask. 本例对应的官方例子是:Query Elevation (Points)和Query Elevation (Lines) 1. 点高程差查询 1.1 结果显示 选了一个明显的点,绿色的是地形变化前的高程点,红色的球是

ArcGIS API for JavaScript 4.2学习笔记[0] AJS4.2概述、新特性、未来产品线计划与AJS笔记目录

放着好好的成熟的AJS 3.19不学,为什么要去碰乳臭未干的AJS 4.2? 诸君,我喜欢嫩的--呸呸呸 诸君,我喜欢3D咋了?新事物会替代旧事物不是~ ArcGIS API for JavaScript 4.2概述 AJS 4.2,即ArcGIS API for JavaScript 4.2,是美国ESRI公司针对WebGIS市场推出的.利用JavaScript和Dojo开发的一款产品,它在2016年12月发布.而AJS 4.0 beta则在一年前就发布了. 关于AJS3和AJS4选择的问题,

ArcGIS API for JavaScript 4.2学习笔记[1] 显示地图

ArcGIS API for JavaScript 4.2直接从官网的Sample中学习,API Reference也是从官网翻译理解过来,鉴于网上截稿前还没有人发布过4.2的学习笔记,我就试试吧. 什么是ArcGIS API for JS?这里就不多介绍了,最关键的一点是4.x版本与3.x版本的变化,按官方的意思是重新写了底层. 笔记中规定: ArcGIS API for JavaScript简称AJS 使用CDN(即不配置本地环境)进行测试开发 其余根据需要进行修改.增删. 要将地图显示在h

ArcGIS API for JavaScript 4.2学习笔记[5] 官方API大章节概述与内容转译

内容如上,截图自ESRI官网,连接:ArcGIS API for JavaScript 4.2 [Get Started] 类似于绪论一样的东西,抽取了最需要关注的几个例子.如:加载Map和View,加载layers,使用弹出窗口,视觉化,与使用窗口小部件.(wtf居然没有分析你想搞事情啊web除了展示难道不应该有()&&*--@) [Mapping and Views] (点击进入我写的章节详细介绍) 最基础的,知道地图和视图的区别,能使用2D和3D地图,对地图的布局有一定的了解,对地图

ArcGIS API for JavaScript 4.2学习笔记[16] 弹窗自定义功能按钮及为要素自定义按钮(第五章完结)

这节对Popups这一章的最后两个例子进行介绍和解析. 第一个[Popup Actions]介绍了弹窗中如何自定义工具按钮(名为actions),以PopupTemplate+FeatureLayer的形式测量要素的长度为例子进行介绍. 第二个[Custom popup actions per feature]则是上一个的升级,如果说上一个例子的功能是写死的,那么这个例子就把这个功能写活了.什么意思呢?上个例子的测距仅仅能测距,没有什么别的特别的.而这个例子以啤酒店的分布(点要素图层)为例,在自

ArcGIS API for JavaScript 4.2学习笔记[7] 鹰眼(缩略图的实现及异步处理、Promise、回调函数、监听的笔记)

文前说明:关于style就是页面的css暂时不做评论,因为官方给的例子的样式实在太简单了,照抄阅读即可. 这篇文章有着大量AJS 4.x版本添加的内容,如监听watch.Promise对象.回调函数.异步处理等内容,原理性的东西我会在文末解释,各位看官不用担心看不懂,我尽量用通俗的语言解释这些. 惯例,如果不习惯从头看到尾,可以直接跳到后面看总结. 大家应该看过商业地图的缩略图功能吧?以度娘地图为例,在使用街景地图的时候,左下角会出现一个地点一样的2D小地图: 这个就是鹰眼功能的应用,在很多桌面

ArcGIS API for JavaScript 4.2学习笔记[24] 【IdentifyTask类】的使用(结合IdentifyParameters类)(第七章完结)

好吧,我都要吐了. 接连三个例子都是类似的套路,使用某个查询参数类的实例,结合对应的Task类,对返回值进行取值.显示. 这个例子是Identify识别,使用了TileLayer这种图层,数据来自Server的MapServer. 结果演示 戳不同的地方会有不同的识别结果. 我对TileLayer不是很了解,这一例仅针对有了解的同学,做一个IdentifyTask的解释. IdentifyTask/IdentifyParameter/IdentifyResult三个类 既然是一样的套路,那么先对

ArcGIS API for JavaScript 4.2学习笔记[9] 同一种视图不同数据(Map)同步

本例子核心:对MapView对象的map属性值进行替换即可达到更改地图数据的效果. 这个例子用的不是Map对象了,而是用的发布在服务器上的专题地图(WebMap)来加载到MapView上进行显示. 在html标签中,使用了section标签,不过没什么稀奇的,就把仨按钮放一块而已. 先给出预览图 三张专题地图:失踪人口密度分布.难民迁徙路线.2015年欧洲来港者. 这个东西很有用,尤其是在展示同一地区的专题地图的时候,这里也展示了什么叫View,什么叫Map. 因为中心点.比例尺是由View对象

ArcGIS API for JavaScript 4.2学习笔记[23] 没有地图如何进行查询?【FindTask类的使用】

从第一篇到现在都是基于地图的,不管怎么样,不管是2D还是3D,至少有个图. 这次来个没有图的例子,看看纯文字的空间查询是什么样的. 本例适用于后台查询或低性能电脑的查询. 预览图 由于4.3和4.2的这个例子没有任何实质性的改动,我直接从官方运行的4.3的例子: 默认打开的时候,按下Find按钮,右边就会出现转圈圈的图,其实是个GIF图片. 结果如上,将Spokane这个County的信息列举出来了,列出的字段有County Name.State.Population(2012).%Popula