首发GIS派:ArcGIS API for JavaScript心得体验
学习和使用ArcGIS API for JavaScript开发差不多有两年了吧,跌跌撞撞断断续续也做了几个小项目,学习之路相对比较平滑,但也遇到不少坑坑洼洼,这些坑大部分是自己当时能力所限造成的,也有的是ArcGIS API本身存在的一些问题,本文主要谈谈我对ArcGIS API使用心得。
对于大部分ArcGIS API for JavaScript的初学者,部署ArcGIS API 肯定也花费了一番功夫(大神例外)。记得当时我部署ArcGIS API整整琢磨了两天,才让“hello world”跑起来。
第一个坑:替换路径要不要加端口
部署过ArcGIS API的朋友都知道,其中部署最关键的一步就是将[HOSTNAME_AND_PATH_TO_JSAPI]
替换为部署后API的HTTP路径。我记得当时我将init.js和dojo.js的[HOSTNAME_AND_PATH_TO_JSAPI]
替换为http://localhost:8080/arcgis_js_api/library/3.19/3.19/
这一步是没有问题的,然后通过script
标签引用:
<script src="http://公网ip/arcgis_js_api/library/3.19/3.19/init.js">script>
大家或许已经发现了,我没有加端口,当时我是这么想的,因为我的tomcat映射了公网IP,而默认端口就是8080,所以理论上没加端口是可以的,而且当时我还在浏览器中确认了通过这个地址是可以访问init.js的。可是,通过不带端口的方式在html中引用却不起作用,这让我百思不得其解。这个问题让我纠结了很久。
第二个坑:替换路径要和引用一致
这个坑快要让我抓狂了,好不容易知道要加上端口后,但是地图始终不能出来,我一直想不明白问题出在哪里,当时还一直以为是自己下载的API文件有缺漏,重新下载了好几回,可依旧都是老样子。但我这种人就是喜欢死磕,有种不达目的决不罢休的蛮劲。第二天起床那会儿,想了下这个问题,突然想到js引用过来,里面的localhost路径会不会成了客户机的localhost了,而实际要指向的应该是服务器的地址,所以会报错。这下我感到顿时又有了希望,唰唰唰起床将init.js和dojo.js的localhost也改成了ip。果然,成功了。
总结
现在想想这两个坑主要还是自己当时的无知吧,其实部署ArcGIS API也很简单,只要将[HOSTNAME_AND_PATH_TO_JSAPI]
替换为部署后API的HTTP路径,而这个路径就是今后在script
引用ArcGIS API的url,不管有没有默认端口,替换时加了端口,引用时也就要用端口;如果是本地部署和本地使用ip可以是localhost,如果是在服务器上部署,其他机器上使用那就必须要用能够访问的ip或域名了。
ArcGIS API for JavaScript是建立在大名鼎鼎的dojo框架之上,所以也就继承了dojo的AMD规范。AMD规范即异步模块加载机制,这种规范让JS就像其它面向对象语言(比如Java)一样,通过模块去管理代码。dojo的模块有点像java的包,而我们所需要的类就是在不同的模块中。
当时我刚看视频加w3school学完了js基础,让我直接跳到JS模块化编程还是有点难以接受的,可是没有办法,不管是官网的demo还是网上的教程都是基于AMD规范的,作为初学者也就没什么选择了。
当时我给自己两个选择:
我选择了依葫芦画瓢,就像找规律一样
require([],function(){
});
先去官网API中找到自己要的类,然后向require中填入即可。比如,我要创建一张地图,就先找MAP类,然后在官网中找到相应位置,向require套入相应的代码
但曾经这段代码让我抓狂过:
<script>
var map;
require([
"esri/map",
"esri/layers/ArcGISDynamicMapServiceLayer"
], function (
ArcGISDynamicMapServiceLayer, Map) {
map = new Map("mapDiv", {
sliderOrientation : "horizontal"
});
var dynamicMapServiceLayer = new ArcGISDynamicMapServiceLayer("https://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Demographics/ESRI_Population_World/MapServer", {
"opacity" : 0.5
});
map.addLayer(dynamicMapServiceLayer);
});
</script>
看似没有什么问题,都是依葫芦画瓢,在require中加入了该加的,但是,地图没出来,后台报错。纠结这里挺久的,后来也是回过去看官网的demo,发现require的第一个参数的顺序要跟回调函数的参数顺序一致。最后解决了这个问题。
上面我们已经说到,ArcGIS API for JavaScript是建立在dojo之上,遵循AMD规范。所以在学习了ArcGIS API一段时间后,我们要有基本的模块编程思想了,不能像一开始那样只知道照着官网的demo去写。
AMD规范简单到只有一个API,即define函数:
define([module-name?], [array-of-dependencies?], [module-factory-or-object]);
其中:
从中可以看到,第一个参数和第二个参数都是可以省略的,第三个参数则是模块的具体实现本身。
具体怎么创建一个模块呢,可以参考这两篇文章:
扩展模块。用面向对象的语言来说就是继承,我们可以继承某个已有的类,然后扩展其功能。最常见的就是TiledMapServiceLayer
类了,我们经常扩展这个类来实现加载非ArcGIS Server发布的切片服务,比如加载天地图切片、谷歌地图切片等。
创建模块。我们可以将一些功能整理成模块,不断积累自己的模块不仅可以大大避免写重复代码,还能巩固和加深对ArcGIS API的学习。比如我们经常要给地图配置一个工具条,工具条实现了地图的基本功能(放大、缩小、平移、坐标拾取、测量等)我们可以将工具条整理成一个模块,这样下次使用时就不用再敲那么多代码了。
很多人问过我为什么要学习ArcGIS API for JavaScript,同样的功能用百度地图API更容易实现。其实问这个问题的人一般不是GIS专业或者是刚开始接触地图开发。的确,百度地图是很强大,我们接触的应用大部分也是基于百度地图API(或高德),可是这些应用用地图的主要目的是展示某些位置信息而已,比如共享单车APP。
在共享单车APP中,地图的主要作用是展示单车和用户的位置,这些展示功能用百度或高德确实很方便。但是当我们要用地图去实现一些复杂功能时,用百度地图API就比较麻烦了,而ArcGIS API能更好的处理这些问题,因为它能和ArcGIS其它产品无缝的对接。比如我们要做一个城市的消防救援系统,最基本的网络分析,如果用百度API去实现这些功能估计够呛,而ArcGIS API却能快速的实现。
其实要想知道ArcGIS API比百度或高德等API的强大之处,打开你ArcGIS的工具箱你就懂了,虽然ArcGIS API还不能完全实现工具箱里的所有功能,但这一定是ArcGIS API的目标吧。
GIS技术交流:GISGO(http://www.gisgo.top)