首页 > 代码库 > Arcgis apis for flex项目实例—开发篇(1):地图浏览

Arcgis apis for flex项目实例—开发篇(1):地图浏览

     前文已经明确数据用天地图,这样的选择一来是免费,二来各种来源的数据都大同小异,天地图用的2000坐标系是常见的经纬度,方便专题数据叠加。

     闲话少说,看一下arcgis api for flex是如何吃定天地图的吧。首先要明确的是我们需要用到四个天地图瓦片服务,分别是经纬度地图底图、经纬度地图中文注记、经纬度影像底图、经纬度影像中文注记,详情可以参阅http://www.tianditu.com/guide/index.html。各种服务形式上都差不多,我们来写一个天地图图层类。

     首先新建一个类,这个类必须是com.esri.ags.layers.TiledMapServiceLayer的扩展。

public class TDTTiledMapLayer extends TiledMapServiceLayer{}

     然后,定义两个变量,_tileInfo、_baseUrl和layerId,_tileInfo是arcgis api瓦片图层的基本参数,_baseUrl是url的基本构成,_baseUrl只是定义了一些必要参数,完整的url还应包括基本地址和瓦片动态参数,再定义一个set属性,用于传入基本地址,瓦片动态参数后面再说,layerId是图层名,这个是天地图服务一个讨厌的参数,同样也要给它一个set属性把这个参数加到地址上。

            private var _tileInfo:TileInfo = new TileInfo();            private var _baseURL:String = "?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles";            private var _layerId:String = "vec";            public function set baseUrl(value:String):void            {                _baseURL = value + _baseURL;            }            public function set layerId(value:String):void            {                _baseURL = _baseURL + "&LAYER=" + value;            }

      然后就是定义_tileInfo了,这是我们这个类最为重要的一步,写一个函数buildTileInfo(),具体内容就不解释了,大致是定义瓦片规格,坐标参考系,以及地图级别。

        private function buildTileInfo():void            {                 _tileInfo.height = 256;              _tileInfo.width = 256;              _tileInfo.origin = new MapPoint(-180, 90);              _tileInfo.spatialReference = new SpatialReference(4490);              _tileInfo.lods = [                  new LOD(1 , 0.703125,    2.958293554545656E8),                   new LOD(2 , 0.351563,    1.479146777272828E8),                   new LOD(3 , 0.175781,    7.39573388636414E7),                    new LOD(4 , 0.0878906,   3.69786694318207E7),                    new LOD(5 , 0.0439453,   1.848933471591035E7),                   new LOD(6 , 0.0219727,   9244667.357955175),                     new LOD(7 , 0.0109863,   4622333.678977588),                     new LOD(8 , 0.00549316,  2311166.839488794),                     new LOD(9 , 0.00274658,  1155583.419744397),                     new LOD(10, 0.00137329,  577791.7098721985),                     new LOD(11, 0.000686646,  288895.85493609926),                   new LOD(12, 0.000343323,  144447.92746804963),                   new LOD(13, 0.000171661,  72223.96373402482),                    new LOD(14, 8.58307e-005, 36111.98186701241),                new LOD(15, 4.29153e-005, 18055.990933506204),                   new LOD(16, 2.14577e-005, 9027.995466753102),                  new LOD(17, 1.07289e-005, 4513.997733376551),                    new LOD(18, 5.36445e-006, 2256.998866688275)               ];        } 

      最后,需要实现一下getTileURL方法,这个方法是把每一张瓦片的动态参数和_baseUrl合并形成每一张瓦片的参数。

            override protected function getTileURL(level:Number, row:Number, col:Number):URLRequest              {                  var url:String = _baseURL + "&TILEMATRIX=" + level + "&TILEROW=" + row + "&TILECOL=" + col;                return new URLRequest(url);              }

      然后,这个类要求我们override几个get方法,照单全收。唯一要注意的是initialExtent,这个可以依据当前地图需要的范围来设定,比如我现在就设成了安徽的。当然也可以随便设,调用时map的extent会覆盖它。

        override public function get fullExtent():Extent           {                return new Extent(-180, -90, 180, 90, new SpatialReference(4326));              }            override public function get initialExtent():Extent           {                return new Extent(114.76,27.59,120.26, 35.64,new SpatialReference(4326));              }           override public function get spatialReference():SpatialReference            {                return new SpatialReference(4490);            }            override public function get tileInfo():com.esri.ags.layers.supportClasses.TileInfo            {                return _tileInfo;            }

     最后在构造函数里写几笔,主要是要把buildTileInfo()加上。

            public function TDTTiledMapLayer()            {                super();                   buildTileInfo();                    setLoaded(true);            }

     好了。类构造完毕,下面我们去调用它。回到我们的index.html,给map加上图层。

    <esri:Map id="map" left="0" right="0" top="0" bottom="0" logoVisible="false" scaleBarVisible="false">        <tool:TDTTiledMapLayer id="vec_c" baseUrl="http://t0.tianditu.com/vec_c/wmts" visible="true"/>        <tool:TDTTiledMapLayer id="cva_c" baseUrl="http://t0.tianditu.com/cva_c/wmts" visible="true"/>        <tool:TDTTiledMapLayer id="img_c" baseUrl="http://t0.tianditu.com/img_c/wmts" visible="false"/>        <tool:TDTTiledMapLayer id="cia_c" baseUrl="http://t0.tianditu.com/cia_c/wmts" visible="false"/>    </esri:Map>

 

     影像底图和注记visible置为false是为了地图切换的需要,初始默认的是线划地图。下面来看效果。

      再利用一点篇幅,把地图类型切换加上吧。两个按钮是toggleButton,其实有很多办法去做这个按钮,但是我们先简单实现一下。加上一个Bool型的Bindable属性IsVector,用它来标识当前地图类型以及控制按钮的状态。

            [Bindable]            private var IsVector:Boolean = true;

      然后,我们在mxml里做一些改动,主要是把ToggleButton的选中状态以及图层可见性绑定过来。

        <esri:Map id="map" left="0" right="0" top="0" bottom="0" logoVisible="false" scaleBarVisible="false">            <tool:TDTTiledMapLayer id="vec_c" baseUrl="http://t0.tianditu.com/vec_c/wmts" layerId="vec" visible="{IsVector}"/>            <tool:TDTTiledMapLayer id="cva_c" baseUrl="http://t0.tianditu.com/cva_c/wmts" layerId="cva" visible="{IsVector}"/>            <tool:TDTTiledMapLayer id="img_c" baseUrl="http://t0.tianditu.com/img_c/wmts" layerId="img" visible="{!IsVector}"/>            <tool:TDTTiledMapLayer id="cia_c" baseUrl="http://t0.tianditu.com/cia_c/wmts" layerId="cia" visible="{!IsVector}"/>        </esri:Map>        <s:HGroup right="10" top="10" height="22" gap="0" verticalAlign="middle">            <s:ToggleButton width="60" label="地图" cornerRadius="0" selected="{IsVector}" click="mapType_clickHandler(event)"/>            <s:ToggleButton width="60" label="影像" cornerRadius="0" selected="{!IsVector}" click="mapType_clickHandler(event)"/>        </s:HGroup>

      下面就把ToggleButton的Click事件绑定上,mxml里我已经写好了,下面看as代码,就一句。

            private function mapType_clickHandler(event:MouseEvent):void            {                IsVector = !IsVector;            }

      这样就好了,两个按钮就和地图的类型绑定在了一起。这里使用flex开发中非常重要的绑定机制,这一机制可以让代码变得非常优雅,但这不是重点,更重要的是,它让逻辑变得简单,也更安全。安全这一点后面遇到类似情况我会提出来。

Arcgis apis for flex项目实例—开发篇(1):地图浏览