ArcGIS.Server.9.3和ArcGIS API for Flex实现自己的Toc控件(三)

时间:2008-10-19 18:12:00 来源:互联网 作者: 神秘的大神 字体:

目的:
1.ArcGIS API for Flex没有提供现成的Toc控件,这里来实现自己的Toc控件。
准备工作:
1.在ArcGIS.Server.9.3发布一个叫USA的Map Service,并且把这个Service启动起来。
完成后的效果图:


开始:
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.esri.com/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.arcgisonline.com/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.esri.com/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.arcgisonline.com/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。这样完成了所有功能就可以运行查询效果了。