背景

近期我司项目的需要,采用Angular(4)+SpringBoot前后端分离的架构。并且在需要在项目中实现Arcgis地图。

像我这种菜鸡遇到这种没有干过的事情肯定是先问百度和谷歌,两个关键词敲下。几乎搜索的内容里很少有两个关键字共存的。但是我这慧眼识得好代码,于是发现了这: https://github.com/Esri/angular-esri-map

Esri是美国环境系统研究所公司,多年来,ESRI公司始终将GIS视为一门科学.也就是说这是官方实例呀。

这样就完了吗?不,事情总是没那么简单的。我以负八级的英文水平开始看这个项目的README,第一行。心都碎了[手动心碎]他是这样说的。

A collection of directives to help you use Esri maps and services in your AngularJS v1.x applications.

wtf?==>AngularJS v1.x applications,我的项目用的可是4.x,这不扯淡?

继续遨游在GayHub[手动滑稽]的代码海洋里。皇天不负有心人让我找到了他:
https://github.com/tomwayson/angular2-esri-example

在这里我尝试将他的项目clone到本地,的确可以跑起来,并且可以看到地图,但尝试获取核心代码但是在包下载的时候就出现了很多问题于是放弃了[真的是无限差包]。

因为之前看到是2.x版本就机遇尝试便没有仔细阅读本项目的说明文档。回去看他的说明文档并把Resources节点下的东西都挨个看了一遍,发现了其中一项貌似很有用:

于是开始阅读这个示例的说明文档,他在文中提到:

This repository is an example of one way to use the ArcGIS API for JavaScript in an application generated with angular-cli.
此存储库是在使用angular-cli生成的应用程序中使用ArcGIS API for JavaScript的一种方法的示例

还有一句:

Adding the ArcGIS API to your own angular-cli application
将ArcGIS API添加到您自己的Angular-cli应用程序

Rather than clone this repository, you should create your own application with the angular-cli and then follow the instructions below to add the above libraries:
而不是克隆此存储库,您应该使用angular-cli创建自己的应用程序,然后按照以下说明添加以上库:

下面的是说明:

  • angular2-esri-loader - a low level service needed to load and use ArcGIS modules (v3.x or v4.x) in your Angular applications
    • 在Angular应用程序中加载和使用ArcGIS模块(v3.x或v4.x)所需的低级服务
  • angular-esri-components - a set of reusable components for use with v4.x (only) of the ArcGIS API
    • 一组(仅)可用于ArcGIS API v4.x的可重用组件

上面的意思已经很清楚。这个项目不建议clone,而是使用angular2-esri-loader 来加载ArcGIS模块,angular-esri-components组件是只能在Arcgis4.x版本中使用的。

当点开angular2-esri-loader这个模块的时候,会很清楚的看到如何安装这个Angular的gis加载库,并且写了示例程序。对于angular有一定的了解的话,这些代码或许就能很清晰的表达出它在做什么。

示例的代码就不列出,可以到github上阅读。大体流程是:

  • npm安装angular-esri-loader,Angular版本不同则安装的命令和库也会存在差异
  • EsriLoaderModule模块加载到程序中
  • 使用EsriLoaderService组件加载地图
  • 文档中加载的是基础图层,但一般开发时会加载缓存地图服务或者其他类型地图服务。这将在我的的示例项目中看到

项目示例:
https://git.oschina.net/StruggleYang/ngGisDemo

项目效果:

你如果看过Arcgis for JavaScript的代码。那么JavaScript代码,如何转换为Angular(TypeScript)的代码,这里我也没有做过多的了解,只是照葫芦画瓢写的一些:

这里推荐去看一下阮一峰的:ES6标准入门可以提供一些参考

下面将做出原生的Arcgis for JavaScript代码和Angular中的书写对比。

变量声明:

1
2
3
4
5
// 有可能你需要在地图初始化前首先声明变量,以便你在任何地方都是可用的

var map; // js

map: any; // ts

地图的模块加载,Arcgis的api是基于dojo框架的,如下:

  • JavaScript中加载地图模块
1
2
3
4
5
6
7
8
9
var map;

require(["esri/map", "dojo/domReady!"], function(Map) {
var map = new Map("map", {
center: [-118, 34.5],
zoom: 8,
basemap: "topo"
});
});
  • Angular中加载地图(基于angular-esri-loader加载器)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // 这里代码并不全,具体请查看上面的示例项目
    .. 省略导入

    @ViewChild('map') mapEl: ElementRef;
    map: any;

    ngOnInit() {
    return this.esriLoader.load({
    // 在js中是不管这个url的,因为它在html中已经引入对应的版本
    url: '//js.arcgis.com/3.18/'
    }).then(() => {
    this.esriLoader.loadModules(['esri/map']).then(([Map]) => {
    this.map = new Map(this.mapEl.nativeElement, {
    center: [-118, 34.5],
    zoom: 8,
    basemap: 'topo'
    });
    });
    });
    }

dojo事件添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
// dojo点击事件添加 by JavaScript
dojo.connect(map, 'onClick', function(evt){
var emp = evt.mapPoint;
var cur_wkid = emp.spatialReference.wkid;
... more code
...
});
...

...
// dojo点击事件添加 by Angular
dojo.connect(this.map, 'onClick', (evt) => {
const emp = evt.mapPoint;
const cur_wkid = emp.spatialReference.wkid;
... more code
...
});
...

这里实际上就是一个箭头函数的区别还有变量的声明区别。

这就结束了?

不不不,远远还不只这些。不论是Angular还是Arcgis,很多东西都没有做过多的了解和深入。不知道那行代码存在隐患。所以革命尚未成功,还得加倍学习和实践巩固。