以下内容,是我在学习Api开发过程中的初始积累,点点滴滴。
1. require([reference package...],function(Class declaration){code...})方法中的引用部分的顺序,必须与function中的类声明的顺序 必须一致,否则找不到对应的类对象,不会报错,但程序无效。
require(["esri/Map", "esri/views/SceneView", "esri/Basemap", "esri/Ground", "esri/layers/WebTileLayer", "esri/layers/ElevationLayer", "esri/layers/FeatureLayer", "dojo/domReady!"], function (Map, SceneView, Basemap, Ground, WebTileLayer, ElevationLayer, FeatureLayer) {
2. 经过几天摸索,仍然无法实现用ArcGis Api for Javascript4.0 来加载ArcGIS Server中发布好的GlobeServer服务,而且网上的示例几乎都是关于利用API来操作MapServer/ImageServer等其它类型的服务,最后不得已求助ESRI北京技术支持,得到答案是,ArcGis Api for Javascript4.0目前还不支持在B/S页面端实现对GlobeServer的操作,只有ArcEngine、ArcObject等C/S端的二次开发才支持GlobeServer。要实现对3D效果的B/S应用,解决方案就是在ArcGIS Server服务端分别将影像图层发布为一个MapService(可包括多个影像图层),DEM高程图层发布为一个ImageService(可包括多个高程图层),然后利用Api在B/S端分别读取MapServer和ImageServer,通过basemap和ground等Map属性来实现三维效果的渲染。
PS:突然想起来还有个WebScene类,其中就讲到了将可以将三维效果场景发布在 ArcGIS Pro或者ArcGIS Online 上,然后通过SceneView来调用,只是在调用的时候,需要指定一个id(如下图代码示例)。
var scene = new WebScene({ // autocasts as esri/portal/PortalItem portalItem: { id: "affa021c51944b5694132b2d61fe1057" // ID of the WebScene on arcgis.com } }); var view = new SceneView({ map: scene, // The WebScene instance created above container: "viewDiv" });
在ArcGis 开发者网站的 Api Reference部分,还介绍了web scenes有两种:global
or local,其中Global scenes把地球描述为球体,而Local scenes
在一个平的表面来描述地球, Global web scenes 通过WebMercator 或者GCS WGS84空间投影来创建,而 local web scenes可以是任何坐标投影,可以在这读取更多关于choosing global or local scenes.
那么就此说来,存在Global web scenes,这就与我通过ArcGlobe发布的GlobeSevice相近,下回研究一下再来发表感想。
ps:这两天又接着查看API Reference的过程中,讲到了SceneView的Viewing modes内容模块,提出分为Globe Scene和Local Scene两种视图模式。
3. 在服务器上发布地图服务,一共有三种方式:1.利用ArcCatalog;2.利用Service Manager发布;3. 在ArcMap的菜单Share As 中选择Service进行发布。
4. 关于Viewpoint的解释,API Reference中是这样说的:
Describes a point of view for a 2D or 3D view. In a 2D view, the viewpoint is determined using a center point and scale value. In a 3D view, it is determined using a camera position. The Viewpoint can be bookmarked for later use, or used for navigation purposes.
翻译理解为:在2D地图MapView 应用中,通常采用Center:[lon,lat]和scale:value属性来设定一个点的视图位置;而在3D SceneView应用中,则通常采用Camera对象,通过设定用camera的position:[lon,lat,z-value]属性和scale属性来定义定一个点的视图位置。
在项目中,我就遇到一个问题,我需要在地图窗口增加一个按钮,用户在操作地图窗口后,单击按钮可回到初始地图视图状态。
(1) 新建一个初始视图控件:
var homeWidget = new Home({ view: mainView }); mainView.ui.add(homeWidget, "manual");
然后运行页面,发现单击按钮后,回到的初始视图状态是地图上方正摄影像方式,而不是我最开始设定的地图初始状态。初始地图设置参数如下代码:
mainView.then(function() { //设置主地图窗口的初始视图 mainView.goTo({ center: [114.532, 31.138], scale: 50000, heading: 35, tilt: 70 }, { animate: true //允许goTo动作以动画形式展现 }); });
查了API Reference,SceneView.goTo()方法中可以定义视图定位到一个viewPoint或camera对象,于是我就想是否可以创建一个viewpoint,然后通过指定地图视图goTo到这个viewpoint位置,我将viewpoint的参数定义到和初始视图位置一样。
var initialViewpoint = new Viewpoint({ camera: { position: [114.532, 31.138], heading: 35, tilt: 70 }, scale:5000, });
(3)在homeWidget的click事件处理函数中设定地图视图goTo到这个viewPoint位置。
on(homeWidget, "click", function () { mainView.then(function () { mainView.goTo(initialViewpoint, { animate: true }); }); });
运行后,单击初始视图按钮,切换位置不是我要的位置,而且地图比例尺缩放到很大。
后来我又发现 homeWidget也有一个viewpoint属性,我设定homeWidget.viewpoint = initialViewpoint;也不行,还是不是回到我要的视图状态。
我自己想了很久,终于发现问题所在。原来我的需求是单击按钮,回到初始视图,而我初始视图状态参数是在mainView.goTo()方法中定义的,如下:
mainView.then(function() { //设置主地图窗口的初始视图 mainView.goTo({ center: [114.532, 31.138], scale: 50000, heading: 35, tilt: 70 }, { animate: true //允许goTo动作以动画形式展现 }); });
视图状态主要通过center、scale、heading、tilt等属性来设定的,其中center[lat,lon]属性与viewpoint对象的camera属性中指定的position[lat,lon]属性应该是有区别的,才造成我单击按钮后,切换视图位置不是我要的初始视图效果。思前想后,我想明白了,原来viewpoint对象是指视点,也就是地图观察者的位置,所以才会出现viewpoint对象中含有camera属性(两者直接的区别是:viewpoint对象包括了camera对象级属性以及scale等其它属性,对象级别更大),SceneView.goTo(target,option)方法中的target对象列举了viewpoint或camera,而我如果把viewpoint或camera作为SceneView.goTo()的target,则试图效果应该是以[lat, lon]为视点的观察视图,并不等同于SceneView.goTo()方法参数中的center[lat,lon]属性的概念。我们要明白,SceneView.goTo()方法中为设置center[lat,lon]属性,是设定地图显示以[lat, lon]为视图中心,配合heading和tilt来确定地图视图效果。而goTo(target,option)方法中的参数target不仅包括viewpoint或camera等对象级属性,也包括了center/scale/zoom/heading/tilt/position等参数属性。如果target参数中设定了viewpoint或camera等对象,则是去设定地图视图定位到某个视点(用户观察点)或相机的位置,而这里的center属性,就是SceneView.center属性,它的定义是用来定义地图视图的中心位置的。
结果豁然开朗,修改homeWidget控件的click事件处理函数,果断实现效果。
//为homeWidget增加click事件处理 on(homeWidget, "click", function () { mainView.goTo({ center: [114.532, 31.138], scale: 50000, heading: 35, tilt: 70 }, { animate: true //允许goTo动作以动画形式展现 }); });
总结:深刻理解Api Reference中对于每个对象语法定义和用法,虽然都是英文,但还是需要深刻理解,否则理解错误了,就用不好这个对象。
5. 关于TileLayer和MapImageLayer的认识:
参考API Reference: https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-TileLayer.html#
The TileLayer allows you work with a cached map service exposed by the ArcGIS Server REST API and add it to a Map as a tile layer. A cached service accesses tiles from a cache instead of dynamically rendering images. Because they are cached, tiled layers render faster than MapImageLayers. To create an instance of TileLayer, you must reference the URL of the cached map service.
理解为:TileLayer是用于一个缓存化的地图服务,通过 ArcGIS Server REST APIl作为 接口,给地图添加一个瓦片式图层。这与动态描述的影像图层不同,因为缓存花的瓦片图层事先在服务器端已经存储好,B/S客户端只需要直接调用已经缓存好的图片即可。通过REST URL地址来进行调用和访问。
To display a map service as a dynamic layer, see MapImageLayer.
理解为:作为动态描述图层,MapImageLayer则把未缓存成瓦片的图层,作为一个动态影像图层来加载,