esri-leaflet入门教程(5)- 动态绘制图形

by 李远祥

在上一章节中已经说明了esr-leaflet是如何加载ArcGIS Server提供的各种服务,这些都是服务本身来决定的,API脚本只是非常简单的调用。但如果要做一列的地图交互操作或者动态渲染等,那就必须使用地图区域跳转、查询结果渲染、动态添加图形等多种交互手段。而这些交互手段基本上离不开一些非服务类型的数据加载,我们可以将其成为动态要素。动态要素一般是在页面端进行动态绘制的。

动态要素这一说法并不是ArcGIS 或者leaflet的说法,而是笔者想了很久之后才编出来的一个名词,为的就是要使ArcGIS JavaScript API 体系与esri-leaflet能找到一个比较好的对应关系,便于ArcGIS的开发人员能够快速的切换过来。esri-leaflet 本身就是基于leaflet去做的扩展,因此,很多情况下都不能摆脱leaflet的限制,文雅点来说就是必须遵循leaflet的定义的接口规范。对于多年ArcGIS开发人员来说,刚开始的时候是有点不习惯的,因为很多时候某些功能和接口不能很好的映射回ArcGIS JavaScript API中。所以,要搞清楚esri-leaflet的使用,那就必须从leaflet本身入手。

在传统的ArcGIS JavaScript API中,要加载一些动态的要素(非直接引用服务的数据),必须使用graphic或者是graphicLayer(其实也是graphic的数组)。graphic在ArcGIS JS里面是由四个部分组成的,分别是geometry(图形)、symbol(符号)、attributes(属性)、infoTemplate(弹窗),如下图

虽然是四个参数,但并不一定要全部使用才能构建,一般来说最基本是需要一个geometry参数就行了,系统会自动给与graphic一个默认的symbol,这样构成一个最简单的graphic,就可以加载到地图上去了。总的来看,ArcGIS的API中是遵循ArcGIS数据的理念,图元(暂且这么说吧,真不知道中文怎么区分graphic和geometry)的显示是读取了要素的图形和属性,并且可以修改其符号(symbol),在地图交互时还可以绑定一些特定的弹出信息。

但在esri-leaflet中,从它提供的基础类来看,根本没有graphic和symbol,就连geometry都没有!这很让人抓狂。为了搞清楚这个关键问题,笔者特意去翻一遍leaflet的接口。终于在leaflet的基础类型中找到了关于图形的一系列接口 http://leafletjs.com/reference-1.0.3.html#layer,其分组也是相当的奇怪,名叫 Vector Layers ,乍一看还以为是一种矢量地图服务,如下图

这个里面就包含了所有的图形定义格式,传统的线、面、圆等都有了,但没有点,因为点是单独的在UI Layers 里面的Marker 。当然了没有arcgis定义的多,但基本也能满足了。再来看其定义是怎样的,点击polyline去查看其构建例子:

// create a red polyline from an array of LatLng points
var latlngs = [
    [45.51, -122.68],
    [37.77, -122.43],
    [34.04, -118.2]
];
var polyline = L.polyline(latlngs, {color: 'red'}).addTo(map);
// zoom the map to the polyline
map.fitBounds(polyline.getBounds());

通过上述代码可以发现几个问题,polyline的构建方式是需要传入点的数组,在构建的时候在其option参数中可以设置其样式,例子中就是使用了color参数,最后图形是可以直接作为Layer加载到地图中,可以与这个图形交互,通过fitBounds 方法跳转到polyline的图形位置。

也有人奇怪,点进polyline和polygon等的这些接口,居然没看到有类似的options可以实现color或者是宽度等设置。那是因为这些接口都在Path中实现,其他的如polyline、polygon、circle等都是实现了path的接口。可以查看下Path的options,如下图

可以看到传统的颜色、线宽、透明度等都可以在options里面设置。

从上面的资料基本上可以看到leaflet与ArcGIS的对应关系了。leaflet中的没有所谓的单独的图元一说,在动态要素来说,全部都是属于Layer,都实现了Layer的接口,其相当于ArcGIS体系中将graphicLayer和graphic 融合在一起,leaflet所谓的图元就是ArcGIS的 graphicLayer+graphics。这感觉还是有点乱,但基本上可以了解leaflet和ArcGIS JS体系的差异。

那么问题来了,由于esri-leaflet 中是没有实现类似ArcGIS JavaScript API中的graphic、geometry、symbol等接口,所有的操作都必须在leaflet的基础体系下完成,那这个代码该怎么编写?

我们可以通过查看esri-leaflet的例子,看看它是如何实现前端加载的。笔者查看的例子在 http://esri.github.io/esri-leaflet/examples/styling-feature-layer-polylines.html 可以看看其截图效果,对道路进行了动态的渲染。

再来看关键代码实现部分

  var map = L.map('map').setView([45.5275, -122.6717], 14);
  L.esri.basemapLayer('Streets').addTo(map);
  var bikePaths = L.esri.featureLayer({
    url: 'https://services.arcgis.com/uCXeTVveQzP4IIcx/ArcGIS/rest/services/Bike_Routes/FeatureServer/0',
    style: function (feature) {
      var c,o = 0.75;
      switch (feature.properties.BIKEMODE) {
        case 'Low traffic through street':
          c = '#007D7D';
          break;
        case 'Bike boulevard':
          c = '#00FF3C';
          break;
        case 'Caution area':
          c = '#FF0000';
          break;
        case 'Local multi-use path':
          c = '#00BEFF';
          break;
        case 'Regional multi-use path':
          c = '#b1a9d0';
          break;
        case 'Moderate traffic through street':
          c = '#FFEB00';
          break;
        case 'Planned multi-use path':
          c = '#000000';
          break;
        case 'Bike lane':
          c = '#328000';
          o = '0.70';
          break;
        case 'High traffic through street':
          c = '#FFA500';
          break;
        case 'Planned bike lane':
          c = '#000000';
          o = '1.0';
          break;
        default:
          c = '#C0C0C0';
      }
      return {color: c, opacity: o, weight: 5};
    }
  }).addTo(map);

可以关键部分是获取了ArcGIS 的Featureservice 的要素,针对要素进行了style的设置,做了一个分等级和颜色的渲染。关键部分是使用了L.esri.featureLayer 接口。从这里可以看到端倪,对于动态的要素的加载,esri也是遵循了leaflet的规则,特意搞什么graphiclayer之类的特殊图层,而是想leaflet一样,直接在Layer中实现,当然这个Layer就是自家的featurelayer了。那传统的graphic前端绘制怎么办?esri-leaflet没有给出答案,笔者看到所有的基于后台服务查询的结果最终都是以featurelayer的形式展示出来,esri-leaflet中根本就没有在客户端绘制图形的接口。其实这部分答案很明确,就是使用leaflet本身的Vector Layers ,开发人员可以直接将其等同于graphiclayer就行了。

为了搞清楚真相,笔者又专门查找了 L.esri.featureLayer 的相关说明,发现其options 的属性里面的style一项居然是实现了leaflet本身的ILayer接口,如下图所示

前面我们看到的Vector Layers 部分其实也是实现了ILayer,也就是说,不管是采用什么样的方式去做动态要素的加载和交互操作,最终还是会落到ILayer和Vector Layers 中去,从ArcGIS的实现方法来看,可见一斑了。

原理清楚之后,所以的问题都可以迎刃而解了,关于代码实现部分就变得异常的简单了。接下来就可以用自己的数据按照例子进行制作一遍。例如笔者现在要按照道路的等级对道路进行实际的渲染,分别采用不同的颜色和粗细来渲染。代码很简单,跟例子差不多,不过就是替换成自己的数据。

function addFeatures() {
 var featlayer =  L.esri.featureLayer({
   url: 'http://localhost:6080/arcgis/rest/services/dongguan/FeatureServer/2',
   style: function(feature) {
    var c, w, o = 0.75;
    switch(feature.properties.type) {
     case '44000':
      c = '#007D7D';
      w = 3;
      break;
     case '45000':
      c = '#00FF3C';
      w = 2;
      break;
     case '51000':
      c = '#FFA500';
      w = 3;
      break;
     default:
      c = '#C0C0C0';
      w = 1;
    }
    return {
     color: c,
     opacity: o
    };
   }
  });
  map.addLayer(featlayer);
 }

这里要注意几点,首先要留意的是esri-leaflet是如何获取要素的属性的,代码中可以看到参数中使用的是 feature.properties.type  其中feature.properties是获取属性的方式,后面加点,接着是字段名(笔者的服务里面使用的是type字段分类)。可以通过arcgis server 的服务路径查看服务的字段情况,例如 http://localhost:6080/arcgis/rest/services/dongguan/FeatureServer/2 道路的要素图层信息如下图所示:

这里还要注意一点就是,arcgis server发布的服务,无论原始数据的字段是否大小写,都会一律转为小写字母,所以要特别注意。还有数据中千万别使用中文作为字段名称,这个大家懂的^_^ 。那么可以看看接下来的效果了,如下图所示

接下来就是自定义的图形加载地图上了。前面已经提及过,这类型的加载方式必须使用leaflet的方式进行。例如我们可以通过以下代码去加载一个面图形,并将其加到地图上面。

function addPolygon(){
 var latlngs = [[23.17, 113.45],[23.15, 113.46],[23.19, 113.46],[23.19, 113.45]];
 var polygon = L.polygon(latlngs, {color: 'red'}).addTo(map);
}

其实际效果如下:

这里值得注意的有几点,一是面图形的构建是一个二维数组,数组元素记录的是xy坐标,但不是[经度,纬度],而是恰好反过来,[纬度,经度]。另外,如果要清除掉动态绘制的图形,那就必须使用ILayer的接口,就是在构建面的时候,其实声明的就是一个Layer,可以利用Layer的remove方法进行清除,在该代码实例中要清除前端的图形,那就是使用 polygon.remove();

由于leaflet对点的绘制做了特别的关照,将它放在UI Layer 而非Vector Layers  中,属于非常个性的部分,如果要加载点的数据,也是可以使用leaflet的方法来构建。但是arcgis server 中的点要素服务,如果要直接动态加载,那L.esri.featureLayer 接口中也有特殊的做法。例如如下核心代码

L.esri.basemapLayer('Streets').addTo(map);
  L.esri.featureLayer({
    url: 'https://services.arcgis.com/rOo16HdIMeOBI4Mb/arcgis/rest/services/Trimet_Transit_Stops/FeatureServer/0',
    pointToLayer: function (geojson, latlng) {
      return L.marker(latlng, {
        icon: icons[geojson.properties.direction.toLowerCase()]
      });
    },
  }).addTo(map);

可以看到,在featurelayer中使用了一个方法是pointToLayer ,强行将esri格式转为L.marker 。说到底还是使用了L.marker接口,只不过是再封装了一层转换而已。具体的代码可在 http://esri.github.io/esri-leaflet/examples/styling-feature-layer-points.html  进行查看。

上面的很多代码都是基于arcgis 的featureservice 是制作的,但也有人会说,featureservice的发布需要后台有ArcSDE支撑,如果没有ArcSDE的数据源,那岂不是连基本的动态要素绘制都不能做?其实不然,这个问题Esri的工程师应该早就想到。看接口名称叫 L.esri.featureLayer  ,不代表它只能支持featureservice,在上述的动态要素加载的代码中,将featureservice改为使用mapservice,同样可以使可运行的,这个只是命名的名称让大家产生误会而已。笔者也特意尝试了一把,将原来的路径替换为 http://localhost:6080/arcgis/rest/services/dongguan/MapServer/2  ,还是能出来原来的结果,因此无需虚惊一场。

总结:总的来说,esri-leaflet在动态要素加载方面还是坚持的不错,尽管大部分的操作都是使用leaflet原有的接口实现。对于从来没有过ArcGIS开发经验的人来说,毫无历史负担,即学即用。对于ArcGIS老鸟来说,还是需要一些时间去琢磨,毕竟一些使用习惯和叫法发生了一定改变。

esri-leaflet入门教程(5)- 动态绘制图形相关推荐

  1. Leaflet学习之路五——动态绘制图形(点、线、圆、多边形)

    leaflet动态绘制图形 动态绘点 动态绘线 动态绘多边形 动态绘制矩形 2020.3.16更新 更新日志: 2019.1.14:更新了绘制多边形时tmpline没有移除的问题 2019.1.15: ...

  2. css中的单位换算_金蝶ERP入门教程:动态换算率及辅助计量单位的应用

    金蝶ERP入门教程:动态换算率及辅助计量单位的应用 关注我,我将定期分享更多的ERP解决方案 如果您喜欢且觉得内容有用,请点击分享转发 如果你有什么关于ERP系统的问题和疑问,可私信联系我 大家好,我 ...

  3. css svg做动图,用svg动态绘制图形

    以此前对svg的了解,就是通过rect/circle/line--等绘制规则图形,或者利用path路径来绘制更复杂的图形.但是这种绘制是,当我们写好svg的xml文件嵌入html代码,页面载入的时候, ...

  4. OpenCV-Python实战(番外篇)——OpenCV中利用鼠标事件动态绘制图形

    OpenCV-Python实战(番外篇)--OpenCV中利用鼠标事件动态绘制图形 使用鼠标事件动态绘制 动态绘制图形 动态绘制图形和文本 相关链接 使用鼠标事件动态绘制 我们已经在<OpenC ...

  5. leafLet入门教程兼leafLet API中文文档参考

    leafLet官方文档链接(英文原版):https://leafletjs.com/reference-1.3.4.html#marker-bindpopup 文章目录 leafLet教程 一.简单入 ...

  6. 动态绘制图形的基本思路

    动态图形绘制的基本思路是,创建一个类继承View类(或者继承SurfaceView类).覆盖onCreate()方法,使用Canvas对象在界面上绘制不同的图形,使用invalidate()方法刷新界 ...

  7. 鼠标移动框选动态绘制图形,基于zrender

    本文只介绍根据鼠标事件动态绘制矩形方法 zrender实现简易画板功能可绘制大部分常用图形在文章末尾可参考 像下图这样,可随心所欲绘制你想绘制的矩形: 完整代码:(有详细注释,有任何疑问欢迎留言) & ...

  8. python之cv2动态绘制图形

    本文部分参考了以下链接内容:https://blog.csdn.net/Vertira/article/details/123631185 代码如下: 说明:按下'c'键实现绘制圆功能:按下'r'键实 ...

  9. html5实现圆圈里带一个三角形,Fabric.js - 详细使用教程1(绘制图形:矩形、圆形、三角形、不规则图形)...

    一.绘制图形 1,绘制矩形 下面代码在画布上绘制一个红色圆角矩形,并带有橙色边框. canvas { border: 1px dashed black; } window.onload = funct ...

最新文章

  1. 2、FreeRTOS任务相关API函数
  2. 机器学习(二)Logistic回归(Logistic regression)算法
  3. 卧式储罐液位体积计算公式excel_ELL外测式液位计在氢氟酸储罐上的实际应用
  4. VTK:Math之PerpendicularVector
  5. SAP Spartacus 中的 Commands and queries
  6. easyui datagrid java_EasyUI DataGrid 显示不了数据????
  7. 小程序制作预算_小程序商城制作多少钱
  8. 失物招领小程序_在机场丢了东西怎么办?温州机场失物招领在线办理平台暖心上线!...
  9. mysql 分表查询外连接_SQL多表连接查询实例(内连接外连接)
  10. 淘宝PK京东:哥刷的不是广告,刷的是存在
  11. C语言 冒泡排序 程序流程图,C语言冒泡排序及流程图(思路解析)
  12. MC 2017数控车床编程基础到精通详细视频教程
  13. 《python网络数据采集》读书笔记
  14. 10.24程序员日,开源社给大家送上大礼!【抢票贴】#疯狂倒计时24小时,10月24-25日I WANT YOU!#...
  15. logstash的dissect匹配字符串内置双引号时需要注意的问题
  16. 上海电气集团数科总经理程艳:工业互联网赋能集团型企业转型发展
  17. 数字图像处理--冈萨雷斯第4版--第一章 绪论
  18. PC版微信  网络不可用,请检查你的网络设置 的解决方法
  19. skywalking agent 导致内存泄漏的一些问题
  20. 趋势操盘法则:资深操盘手6年60倍实战选股技法

热门文章

  1. hive 直接访问mysql_hive 直接插入mysql
  2. python3怎么使用pyrex_python pyrex windows 编译C可执行文件
  3. ❤️《大前端—Webpack》
  4. 微信浏览器如何禁止iPhone手机上下滑动网页
  5. Swiper 在vue中的使用,loop=true获取真实index,数据更新刷新初始化swiper
  6. 三、synchronized同步锁
  7. Unity(TransForm)
  8. 云存储是否能拯救数据泛滥
  9. 快递实名制正式实施 市民最担心个人信息泄露
  10. 2017全球光伏增速或放缓 国内“6·30”仍将是分水岭