zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    我理解的 js 异步成长总结
    小程序 获取地理位置-- wx.getLocation
    H5页面在微信端的分享
    ES6 我的总结学习
    5 分钟掌握 JS 实用窍门技巧,帮你快速撸码--- 删除数组尾部元素、E6对象解构、async/await、 操作平铺嵌套多维数组等
    小程序 video 层级,原生组件
    React 事件 传参
    微信小程序中如何使用setData --- 修改数组对象、修改对象
    流氓式--小程序用户授权 --- 小程序授权、获取用户信息
    深度学习的反向传播笔记
  • 原文地址:https://www.cnblogs.com/onsummer/p/6682674.html
Copyright © 2011-2022 走看看