ArcGIS API for JavaScript 4.2学习笔记[29] 热点(密度)分析——以报警频率为例【使用Geoprocessor类】...

这个就颇有插值分析的样子了。也可以说是密度分析。做出来就是一个热力地图的样子。

比如,人口密度,降雨分布等。这都可以由这个例子做出来类似的。

由于上一篇已经介绍过Geoprocessor类和ParameterValue类了,所以这节就略去这些内容。想知道的同学可以点击这里,看上一篇相关内容。

与上一节不同的是,使用的不是execute()方法了,而是submitJob()方法,这是一个异步操作方法。尽管他们返回的类型是类似的。

官方给的解释很简洁明了,有了前几个的基础几乎可以瞬间抓住重点,如submitJob的参数的获取,对热力图结果如何获取和处理等,自行查询API即可。

我这篇博客则是对这个例子进行重点全解析。如果是老鸟,请直接看:How it works

 


看看结果

给定一个时间范围,就能查询该地区报警的频率。这里使用了图例这个widget,对其有读写操作。图中默认的时间按下红色按钮后,就可以看到如图的结果(3-5s)。

最中央红色区域是报警最频繁的区域,点状符号代表报警的时间(星期几)。

据说这个例子有点长,加油。

给出引用

require([
    "esri/Map",
    "esri/views/MapView",
    "esri/tasks/Geoprocessor",
    "esri/widgets/Legend",
    "esri/widgets/Spinner",
    "esri/layers/support/ImageParameters",

    "dijit/form/DateTextBox",
    "dojo/dom",
    "dojo/dom-construct",
    "dojo/on",
    "dojo/date/locale",
    "dojo/parser",
    "dijit/registry",
    "dojo/domReady!"
  ],
    function(Map, MapView, Geoprocessor, Legend, Spinner, ImageParameters,
    DateTextBox, dom, domConstruct, on, locale, parser, registry) {
    ...
    }
);

dijit这个东西是第三方控件(貌似),看DateTextBox就知道了。AJS4.x除了dojo也有用dijit(不明白为啥名字那么奇怪)

三个新鲜的玩意儿:Legend、Spinner和ImageParameters。

函数骨架

function(...){
    parser.parse();//不知道干啥用的
    on(dom.byId("hotspotButton"), "click", findHotspot);
    
    var map = new Map({...});
    var view = new MapView({...});
    
    //实例化GP
    var gpUrl = ".../GPServer/XXX";//省略,但是还是GPServer
    var gp = new Geoprocessor(gpUrl);
    gp.outSpatialReference = {...}
    
    //图例
    var legend = new Legend({...});
    spinner = new Spinner({...});
    domConstruct.place(spinner.domNode, view.root);

    //数据处理的重点部分,也是官方How it works主要涉及的部分
    function findHotspot(){...}
    function buildDefinitionQuery(){...}
    function cleanup(){...}
    function drawResultData(result){...}

    //非重点
    function progTest(value){...}
    function errBack(err){...}
}

按照官方的套路来,会更容易懂。那么久直接从findHotspot()、buildDefinitionQuery()、cleanup()、drawResultData(result)这四个方法说起吧。

How it works

允许我模仿一回官方的标题~

findHotspot():分析按钮的click事件,设置gp.submitJob()的参数对象params,并执行分析;在这里,使用了异步操作分析,终于看到了完整的then写法。

buildDefinitionQuery():gp.submitJob()的参数对象的生成方法,该方法返回了一个Object对象,供submitJob()使用。

cleanup():遍历map中的layer,如果发现名字全等于"HotspotLayer",移除。

drawResultData(result):绘制分析结果。

findHotspot()

function findHotspot() {
  var params = {
    Query: buildDefinitionQuery()
  };
  cleanup();

  spinner.viewModel.point = view.center;
  //经典的完整then()写法  
  gp.submitJob(params).then(drawResultData, errBack, progTest);
}

通过buildDefinitionQuery()获取需要的参数。

then写法,第一个drawResultData()是分析成功时要做的事情:绘制结果;

errBack()是分析失败要做的事情;

progTest()则是测试分析进展。

后两个比较简单,这样的写法类似try catch异常处理。

buildDefinitionQuery()

function buildDefinitionQuery() {
  var defQuery;
  var startDate = locale.format(registry.byId('fromDate').value, {
    datePattern: 'yyyy-MM-dd hh:mm:ss',
    selector: 'date'
  });
  var endDate = locale.format(registry.byId('toDate').value, {
    datePattern: 'yyyy-MM-dd hh:mm:ss',
    selector: 'date'
  });
  var def = [];
  def.push("(Date >= date '" + startDate + "' and Date <= date '" +
    endDate + "')");
  def.push(
    "(Day = 'SUN' OR Day= 'SAT' OR Day = 'FRI' OR Day ='MON' OR Day='TUE' OR Day='WED' OR Day ='THU')"
  );

  if (def.length > 1) {
    defQuery = def.join(" AND ");
  }
  return defQuery;
}
buildDefinitionQuery()方法

使用locale.format方法获取时间控件上的时间,分别为startDate和endData两个Object变量;

然后根据日期范围,设定一组SQL语句(应该是,语法比较怪异),名为def(装箱为String[])

最后把数组通过AND来链接成一个长字符串,赋值给defQuery这个变量,并返回defQuery变量作为返回值,也即为submitJob()的参数。

drawResultData(result)

function drawResultData(result) {
  var imageParams = new ImageParameters({
    format: "png32",
    dpi: 300
  });
    
  var resultLayer = gp.getResultMapImageLayer(result.jobId);
  resultLayer.opacity = 0.7;
  resultLayer.title = "HotspotLayer";

  map.layers.add(resultLayer);
  spinner.viewModel.point = null;
}

ImageParameters这个类是什么东西完全不知道...new出来完全没看懂哪里有用,各位可以试试删除这个实例再运行。//怀疑是SDK开发人员忘记删了。

从gp中获取MapImageLayer,这个getResultMapImageLayer()是个新方法,返回指定id的MapImageLayer实例。这里返回的MapImageLayer实例名为resultLayer。

设置好透明度和名字后,加入到map的layers中。这就算完成了。

 

最后再上一张逻辑图:

至于图例widget和那个啥spinner就不作为重点啦~有兴趣的同学可以深究一下,应该在widget章节有详细的说明的。

再次感叹then这个东西的强大之处,Promise对异步操作真的太方便了。

总结一下

...???上面那张逻辑图不就说明了一切吗???

黑人问号.jpg

转载于:https://www.cnblogs.com/onsummer/p/6682674.html

好的,我会注意保密。针对你的问题,我来给你解答一下。 对于弹窗的位置,可以通过设置弹窗的锚点(anchor)和偏移量(offset)来进行调整。锚点可以是弹窗的中心点(center)、右上角的点(upper-right)、左上角的点(upper-left)、左下角的点(lower-left)或者右下角的点(lower-right)。偏移量可以分别设置水平和垂直方向的偏移量,可以为正数或负数。 下面是一个示例代码: ``` require([ "esri/Map", "esri/views/MapView", "esri/widgets/Popup", "dojo/dom-construct", "dojo/dom-style", "dojo/on", "dojo/domReady!" ], function(Map, MapView, Popup, domConstruct, domStyle, on) { var map = new Map({ basemap: "streets" }); var view = new MapView({ container: "viewDiv", map: map, center: [-118.805, 34.027], zoom: 13 }); var popup = new Popup({ anchor: "center", // 设置锚点为中心点 offset: [0, -15], // 设置垂直方向的偏移量为-15 visibleWhenEmpty: false, // 当没有内容时不显示弹窗 view: view }); view.popup = popup; view.on("click", function(event) { var lat = event.mapPoint.latitude.toFixed(3); var lon = event.mapPoint.longitude.toFixed(3); var content = domConstruct.create("div", { innerHTML: "Latitude: " + lat + "<br>Longitude: " + lon }); popup.content = content; popup.open({ location: event.mapPoint }); }); }); ``` 对于为弹窗添加元素,可以使用 dojo/dom-construct 模块来进行创建和添加。可以使用这个模块的 create() 方法来创建 HTML 元素,然后使用 popup.content 属性来添加到弹窗中。 下面是一个示例代码: ``` var content = domConstruct.create("div", { innerHTML: "<b>Hello, world!</b>" }); popup.content = content; popup.open({ location: event.mapPoint }); ``` 希望这些信息能够帮到你,如果你还有其他问题,请随时提出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值