1、 结构图以及解析
下图是ESRI提供的开发帮助里面对其结构的一个描述图,本人做了一些归类:
A部分:这一部分是项目中的组件列表,包括一些配置文件、Module(就是Widget)、组件等等。这些组件在没有经过组织之前是完全孤立的。它们主要完成一些界面显示和业务逻辑。
B部分:该部分的主要功能就是将A部分中相互完全孤立的文件列表,不管是业务层还是界面层进行一个组织,将他们之间关联起来,便于程序的统一管理和开发。其中对于将这些文件或者组件综合起来的一个非常重要的一个内容就是container(在viewer中叫做SiteContainer容器),关于container是如何组织这些组件的,在SiteContainer解析一文中将会详细阐述。
C部分:我们可以将该部分称作数据层,也就是说这一层是提供数据的,不管是地图数据还是常规数据,都是通过这一层获取的,关于这一层在Viewer中并不明显,其贯穿于整个系统的各个角落。本人愚见,此处也是Viewer需要改进的地方。
在下面的文章里,我们主要基于这三部分对FlexViewer进行解析。
理解了Viewer的这三部分,那么在Viewer中是如何具体的进行文件或者说组件组织的那?
2、 文件组织
首先我们还是看下Viewer的效果图,同样将其分成几个部分,我们在将这些部分进行一一介绍。
我同样将其分成三个大的组件部分。
A部分:该部分是地图显示部分,也是系统的主体部分,地图的一些显示配置和基本操作都在该部分中。对于该部分的定义,我们在Viewer中不难找到,那就是FlexVIew文件夹下面的
com/esri/solutions/flexviewer/MapManager.mxml
该文件中定义个,地图的添加以及一些地图的基本操作。
map = new Map();
map.id = "map";
map.zoomSliderVisible = false;
map.addEventListener(MapEvent.LOAD, mapLoadComplete);
this.addChild(map);
这几行代码完成了对map控件的添加,下面的部分就是图层的添加以及一些配置,包括一些工具定义:
navToolbar = new Navigation();
navToolbar.map = map;
drawToolbar = new Draw();
drawToolbar.map = map;
这两行代码,为地图添加了一个浏览工具和一个绘图工具。
B部分:该部分是一个控制条,用来控制整个系统的用户操作。其主文件为:
com/esri/solutions/flexviewer/Controller.mxml
打开之后我们发现其显示部分很简洁:
<comp:Banner id="banner" status="{status}"/>
<mx:HBox id="menuContainer" horizontalGap="-25"
horizontalCenter="0" y="{banner.height - 20}"/>
其实其使用了一个定义好的组件Banner,这个组件才是这个控制条信息的主体部分。而control只是为这个组件提供必须的配置信息。
Banner组件位于components文件夹下,打开它,仔细查看其中的内容,我们就可以明白Viewer里面的B部分是怎么出来的了。
然后我们说说B部分的菜单是如何出来的。在Controller仅仅的两行设计代码里面我们可以看到有个叫做menuContainer的HBox,他就是负责显示菜单的。在程序的配置文件加载完成后,这个界面就会执行对菜单的配置,也就是下面的一个函数:
private function configureMenus():void
{
for (var i:Number = 0; i < configData.configMenus.length; i++)
{
var menuId:String = configData.configMenus[i].id;
var menuLabel:String = configData.configMenus[i].label;
var menuIcon:String = configData.configMenus[i].icon;
var menuItems:Array = configData.configMenus[i].items;
var controllerMenu:ControllerMenu = new ControllerMenu();
controllerMenu.id = menuId;
controllerMenu.menuLabel = menuLabel;
controllerMenu.menuImage = menuIcon;
controllerMenu.menuCollection = new ArrayCollection(menuItems);
menuContainer.addChild(controllerMenu);
}
var bw:Number = configData.configMenus.length * 90;
if (bw > banner.minWidth)
banner.width = bw;
}
这里面使用了另外一个组件ControllerMenu,其定义位于Banner.mxml同目录下的ControllerMenu.mxml中,这个组件就是完成主菜单定义的主要控件。对于子菜单的定义我们在ControllerMenu中可以看到这句代码:
<mx:Repeater id="menuRepeater" dataProvider="{menuCollection}">
<comp:ControllerMenuItem itemId="{menuRepeater.currentItem.id}"
itemLabel ="{menuRepeater.currentItem.label}"
itemIcon ="{menuRepeater.currentItem.icon}"
itemRuleVisible ="{menuRuleVisible(menuRepeater.currentIndex)}"
itemAction ="{menuRepeater.currentItem.action}"
itemValue ="{menuRepeater.currentItem.value}" />
</mx:Repeater>
这个Repeater就是用来完成子菜单信息绑定的。其中使用了关于子菜单的组件ControllerMenuItem,我们打开这个子菜单的定义,可以清楚地看到关于子菜单的点击事件和一些效果代码。这就是菜单的实现方式。
以上就是Viewer左上侧控制条的实现流程。
C部分:这一部分的实现相对比较复杂,主要是在其管理上面,再加上其使用Module的方式加载显示,所以感觉上相对复杂。