目的: 1.ArcGIS API for Flex没有提供现成的Toc控件,这里来实现自己的Toc控件。 准备工作: 1.在ArcGIS.Server.9.3发布一个叫USA的Map Service,并且把这个Service启动起来。 完成后的效果图:
![](http://image109.360doc.com/DownloadImg/2018/07/1716/138761487_1_2018071704272397.jpg) 开始: 1.启动Flex Builder3新建工程以及引入ArcGIS API for Flex library的开发包,这个过程前面2篇都讲过了这里就不啰嗦了。 2.新建LayersOnAndOff.mxml页面,然后在页面上添加Map控件以及设置ArcGISDynamicMapServiceLayer,添加一个ComboBox控件用来地图切换显示。具体代码如下:
1 <?xml version="1.0" encoding="utf-8"?> 2 <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" backgroundColor="white" xmlns:esri="http://www./2008/ags" > 3 <mx:Array id="arr"> 4 <mx:Object label="USA" data="http://jh-53a435fbc0e8/ArcGIS/rest/services/USA/MapServer" /> 5 <mx:Object label="USA_2D" data="http://sampleserver1./ArcGIS/rest/services/Demographics/ESRI_Population_World/MapServer" /> 6 </mx:Array> 7 <mx:ComboBox id="myURL" selectedIndex="0" horizontalCenter="-329" dataProvider="{arr}" y="10"> 8 </mx:ComboBox> 9 <esri:Map logoVisible="false" panArrowsVisible="true" width="463" height="288" x="33" y="40" borderStyle="solid" borderThickness="3"> 10 <esri:ArcGISDynamicMapServiceLayer id="myDynamicService" url="{myURL.selectedItem.data}" load="myDynamicService.defaultVisibleLayers()"/> 11 </esri:Map> 12 </mx:Application>
3.对上面的代码做一下解释,首先添加了一个id为arr的对象数组作为ComboBox的数据源,arr的对象数组包含2个对象:一个是上面发布的USA得rest地址,一个是Esri提供的在线的rest地址。然后在Map控件的ArcGISDynamicMapServiceLayer的url属性绑定ComboBox的选择值,这样当ComboBox选择发生变化时地图也会根据rest地址进行切换显示。 4.接下来做Toc控件了,首先在src目录下新添加一个叫uc的目录,然后在uc下新建TreeToc.mxml文件这个就是用来实现Toc功能的。Toc控件这里是用Flex提供的Tree控件的基础上实现的,具体代码如下:
1 <?xml version="1.0" encoding="utf-8"?> 2 <mx:Tree xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%" fontSize="12"> 3 <mx:Script> 4 <![CDATA[ 5 import mx.collections.ArrayCollection; 6 import com.esri.ags.layers.ArcIMSMapServiceLayer; 7 import com.esri.ags.layers.ArcGISDynamicMapServiceLayer; 8 import com.esri.ags.events.LayerEvent; 9 import com.esri.ags.layers.Layer; 10 import com.esri.ags.layers.LayerInfo; 11 import mx.utils.ObjectUtil; 12 13 private var layerInfos:Array; 14 //图层 15 private var _layer:Layer; 16 //图层是否更新标识 17 private var _layerChanged:Boolean; 18 //获取图层 19 public function get layer():Layer 20 { 21 return _layer; 22 } 23 //设置图层 24 public function set layer(value:Layer):void 25 { 26 _layer = value; 27 _layerChanged=true; 28 invalidateProperties(); 29 } 30 //设置组件属性 31 override protected function commitProperties():void 32 { 33 if (_layerChanged) 34 { 35 _layerChanged = false; 36 if(layer) 37 { 38 //为layer添加完成后取消鼠标忙碌显示的监听事件 39 layer.addEventListener(Event.COMPLETE, removeBusyCursor, false, 0, true); 40 //为layer添加发生错误后取消鼠标忙碌显示的监听事件 41 layer.addEventListener(IOErrorEvent.IO_ERROR, removeBusyCursor, false, 0, true); 42 43 if(layer.loaded) 44 { 45 //如果layer载入完成为DataGrid设置数据源 46 setDataProvider(); 47 } 48 else 49 { 50 //如果未载入完成为layer添加载入监听事件 51 layer.addEventListener(LayerEvent.LOAD, layerLoadHandler, false, 0, true); 52 } 53 } 54 } 55 super.commitProperties(); 56 } 57 //设置数据源 58 private function setDataProvider():void 59 { 60 if(layer is ArcGISDynamicMapServiceLayer) 61 { 62 layerInfos=ArcGISDynamicMapServiceLayer(layer).layerInfos; 63 } 64 else if(layer is ArcIMSMapServiceLayer) 65 { 66 layerInfos = ArcIMSMapServiceLayer(layer).layerInfos; 67 } 68 registerClassAlias("com.esri.ags.layers.LayerInfo", LayerInfo); 69 //ObjectUtil.copy方法接受一个对象做为参数而返回一个在内存的新位置的此对象的深度拷贝,类似克隆 70 layerInfos = ObjectUtil.copy(layerInfos) as Array; 71 dataProvider = layerInfos; 72 //labelField="name"; 73 74 } 75 76 private function layerLoadHandler(event:LayerEvent):void 77 { 78 setDataProvider(); 79 } 80 //显示图层方法 81 public function showLayer(layerInfo:LayerInfo):void 82 { 83 var visibleLayers:ArrayCollection; 84 if(layer is ArcGISDynamicMapServiceLayer) 85 { 86 //获取当前可见图层列表 87 visibleLayers=ArcGISDynamicMapServiceLayer(layer).visibleLayers; 88 //在当前可见图层列表中加入要显示的图层 89 visibleLayers.addItem(layerInfo.id); 90 } 91 else if(layer is ArcIMSMapServiceLayer) 92 { 93 //获取当前可见图层列表 94 visibleLayers=ArcIMSMapServiceLayer(layer).visibleLayers; 95 //在当前可见图层列表中加入要显示的图层 96 visibleLayers.addItem(layerInfo.id); 97 } 98 //设置鼠标显示状态 99 if (visibleLayers) 100 { 101 cursorManager.setBusyCursor(); 102 } 103 } 104 //隐藏图层方法 105 public function hideLayer(layerInfo:LayerInfo):void 106 { 107 var visibleLayers:ArrayCollection; 108 if(layer is ArcGISDynamicMapServiceLayer) 109 { 110 //获取当前可见图层列表 111 visibleLayers=ArcGISDynamicMapServiceLayer(layer).visibleLayers; 112 //查找要隐藏的图层的index 113 var index:int=visibleLayers.getItemIndex(layerInfo.id); 114 //在当前可见图层列表中去除要隐藏的图层 115 if (index != -1) 116 { 117 visibleLayers.removeItemAt(index); 118 } 119 } 120 else if(layer is ArcIMSMapServiceLayer) 121 { 122 //获取当前可见图层列表 123 visibleLayers=ArcIMSMapServiceLayer(layer).visibleLayers; 124 //查找要隐藏的图层的index 125 var index2:int=visibleLayers.getItemIndex(layerInfo.id); 126 //在当前可见图层列表中去除要隐藏的图层 127 if (index2 != -1) 128 { 129 visibleLayers.removeItemAt(index2); 130 } 131 } 132 //设置鼠标显示状态 133 if (visibleLayers) 134 { 135 cursorManager.setBusyCursor(); 136 } 137 } 138 139 private function removeBusyCursor(event:Event):void 140 { 141 //删除忙光标 142 cursorManager.removeBusyCursor(); 143 } 144 ]]> 145 </mx:Script> 146 <mx:itemRenderer> 147 uc.TreeRenderer 148 </mx:itemRenderer> 149 </mx:Tree> 150
5.对上面的代码做一下解释,首先Toc控件是在Tree控件的基础上实现的,这个Tree控件获取Layers数据作为数据源进行绑定显示,同时提供了显示图层隐藏图层等方法。最后这个Tree添加了一个叫uc.TreeRenderer的itemRenderer(项渲染器),也就是说Tree的每一个节点都是由这个itemRenderer来负责显示。那也就是说还需要实现uc.TreeRenderer的功能。 6.在uc目录下新增加TreeRenderer.mxml的文件,这个因为是itemRenderer所以需要implements="mx.controls.listClasses.IDropInListItemRenderer",具体代码如下:
1 <?xml version="1.0" encoding="utf-8"?> 2 <mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" horizontalAlign="left" implements="mx.controls.listClasses.IDropInListItemRenderer"> 3 <mx:Script> 4 <![CDATA[ 5 import com.esri.ags.layers.LayerInfo; 6 import mx.controls.listClasses.BaseListData; 7 8 //图标图片 9 [Bindable] 10 [Embed(source="assets/Dataframe.GIF")] 11 public var layericon:Class; 12 13 private var _listData:BaseListData; 14 15 public function get listData():BaseListData 16 { 17 return _listData; 18 } 19 20 public function set listData(value:BaseListData):void 21 { 22 _listData = value; 23 } 24 //checkbox的点击事件 25 private function clickHandler(event:MouseEvent):void 26 { 27 var layerInfo:LayerInfo = LayerInfo(data); 28 29 if (cb.selected) 30 { 31 layerInfo.defaultVisibility = true; 32 //调用TreeToc显示图层方法 33 TreeToc(listData.owner).showLayer(layerInfo); 34 } 35 else 36 { 37 layerInfo.defaultVisibility = false; 38 //调用TreeToc隐藏图层方法 39 TreeToc(listData.owner).hideLayer(layerInfo); 40 } 41 } 42 ]]> 43 </mx:Script> 44 <mx:CheckBox id="cb" selected="{data.defaultVisibility}" click="clickHandler(event)"/> 45 <mx:Image source="{layericon}"/> 46 <mx:Label text="{data.name}"/> 47 48 </mx:HBox> 49
7.上面的代码中主要是在HBox控件中放了一个CheckBox、一个Image、一个Label,并且为CheckBok添加了点击事件可以控制图层的隐藏显示。 8.这样完成了Toc控件的开发,接下来是要在LayersOnAndOff.mxml页面使用这个控件,增加如下代码(红色部分):
1 <?xml version="1.0" encoding="utf-8"?> 2 <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" backgroundColor="white" xmlns:esri="http://www./2008/ags" xmlns:uc="uc.*" > 3 <mx:Array id="arr"> 4 <mx:Object label="USA" data="http://jh-53a435fbc0e8/ArcGIS/rest/services/USA/MapServer" /> 5 <mx:Object label="USA_2D" data="http://sampleserver1./ArcGIS/rest/services/Demographics/ESRI_Population_World/MapServer" /> 6 </mx:Array> 7 <mx:ComboBox id="myURL" selectedIndex="0" horizontalCenter="-329" dataProvider="{arr}" y="10"> 8 </mx:ComboBox> 9 <esri:Map logoVisible="false" panArrowsVisible="true" width="463" height="288" x="33" y="40" borderStyle="solid" borderThickness="3"> 10 <esri:ArcGISDynamicMapServiceLayer id="myDynamicService" url="{myURL.selectedItem.data}" load="myDynamicService.defaultVisibleLayers()"/> 11 </esri:Map> 12 <uc:TreeToc layer="{myDynamicService}" height="288" width="210" x="504" y="40" borderThickness="3"/> 13 </mx:Application> 14
9.上面代码的红色部分添加了TreeToc,并且设置了一个layer的属性值是绑定myDynamicService。这样完成了所有功能就可以运行查询效果了。
|