文章版权由做者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/。前端
在GIS中元素通常分为点元素,线元素,面元素以及symbol元素(特殊的点元素)等。与此对应,图层能够分为点图层,线图层,面图层以及标注图层等。从第9章到第10章,我给你们讲解了什么是矢量数据、矢量数据的来源、矢量数据的构造、以及矢量数据中的地理坐标与屏幕坐标之间的转换。在了解了这些概念和算法以及流程后,这一章咱们将开始讲解设计出一个矢量图层前的最后一步,设计WebGIS中的要素(Feature)。算法
要素应该具备以下功能:设计模式
(1)可以绘制出矢量数据的Shape。框架
(2)可以存储矢量数据的atrributes。函数
(3)能够响应鼠标事件。设计
(4)能够响应自定义事件,如自定义的一系列地图事件。对象
(5)可以添加入Canvas组成一个矢量图层。blog
(6)要素是有不少种类的,好比点、线、面等。继承
(1)在前面咱们已经阐述了要素的本质,即UIComponent。由于UIComponent是前端语言中已经封装好了的类,咱们只用继承其便可,如此咱们便同时能实现上面所说的第三个需求以及第五个需求。接口
(2) 需求中要求要素中可以绘制出矢量数据的Shape。因此得定义相似于Draw这样的功能函数,以解决第一个需求。
(3)要素中还须要有个一变量存放attributes,即FeatureInfo以解决第二个需求。
(4)设计的类中还要定义一个监听事件的函数和一个移除监听事件的函数,即:addMapEventListener和removeMapEventListener,以解决第四个需求。
当地图刷新,好比放大和缩小时,此时的UIComponent必须重绘,不然地图上的Shape将再也不在地图上表示正确的位置,因而这里对Feature的设计有两点须要注意:
(1)对地图放大和缩小进行监听。
(2)增长重绘函数,即reDraw函数。当地图放大和缩小时触发重绘函数。
需求中提到了要素具备多种类型,咱们设计时须要将这几种类型均涉及到的属性和函数抽象出来做为一个基类,即Feature类。能够抽象出来的属性和类有:
(1)reDraw和Draw函数
(2)FeatureInfo属性
(3)addMapEventListener和removeMapEventListener函数
(4)对地图放大缩小事件的监听,此功能的实现能够放在Feature的构造函数中。
在绘制shape时,咱们须要用到地理坐标与平面坐标互相转换的函数,即上一章提到过的geoXYToScreenXY和screenXYToGeoXY。可是这两种方法是不可能封装到Feature类中的。由于这两种方法为系统中通用方法,不是专为Feature类而存在。因此这两个方法是放在主框架类中,这里我将这个主框架定义为FrameMap。因而,咱们的Feature类中还应该有能够注入主框架的属性,即Map。
基于上述分析,咱们如今要开始真正的设计要素了。咱们首先定义一个Feature类,其继承于UIComponent,而后再根据需求定义一系列具体的基础要素类,好比PointFeature、LineFeature和PolygonFeature等。而且若是需求出现变动,原有的基础要素已经不能知足需求时,能够在基础要素上进行继承从而进一步扩展基础要素类。
以下是最后设计出的要素类的UML图:
在实际应用中,对同一个要素,用户须要的展示方式可能不尽相同。好比对面要素,有时候须要展示成黄色,有时候须要展示成蓝色等,而有时候须要面要素内的填充为网格状,有时候须要面在移动上去时变色,有时候又不须要等等。
解决此问题的方法,并非去为每种需求从新将基础要素继承,而后修改draw方式,若是这样的话,代码的重复量太大。在设计模式中,咱们有一个原则是能用组合时尽可能用组合,能不用继承时尽可能不用继承,由于继承是种高度的耦合,派生类和基类被牢牢的绑在一块儿,灵活性大大下降,并且,滥用继承,也会使继承树变得又大又复杂,很难理解和维护。在这个需求里,目前用不上组合,可是继承就更不须要了。
咱们的解决方法通常是:
(1)首先将需求分类。外观上:一类是改变颜色的,一类是改变要素内部构造的。行为上:一类是须要某些监听而且作出相关变化的,一类是不须要某些监听的。这样咱们能够在具体要素类,好比polygon类中添加两个共有属性,一个是DrewType,一个是ActionType。若是不但愿把控制行为的重担都放在polygon类中,咱们也能够不用定义ActionType,此类中原本就设计有addMapEventListener和removeMapEventListener。能够开放给调用者,让其自行判断。
(2)而后咱们在Draw函数中,经过判断DrawType来进行绘制方面的控制。每一个具体要素类中有本身定义的内部透明度(Sopacity)、外部透明度(opacity)以及内部填充色(SColor)和外部填充色(color)以及填充图标(Symbol)等等绘制方面的属性。回到上面的需求中,咱们一类是想改变要素颜色,一类是想改变内部构造。仍是假设这是一个对于polygon要素的需求,咱们把DrawType定义为0和1。当DrawType为0时,咱们将使用Sopacity,opacity、Scolor和color等绘画要素进行绘制,这些要素均是有默认值的公有属性,调用者能够本身设定。可是当DrawType是1时,这时候会将Symbol进行加载,而后改变绘制polygon的方式,将Symbol做为内部填充物进行填充。一样,Symbol也是有默认值的公有属性,调用者能够本身设定。
在后面探讨设计WebGIS的地图平移功能时,咱们会讲到每次地图被拖拽后,矢量图层(Canvas)的左上角坐标均会加减相同的屏幕平移量。这时候若是仅仅是将要素中的地理坐标转换为屏幕坐标后就直接将其绘制在UIComponent,而后添加到该Canvas里,便会出现绘制的要素不在地图上实际的地点的现象,即发生了偏移。这个问题是一个有必定难度的问题,我会在之后的WebGIS基础功能设计篇里专门花一个章节跟你们探讨这个问题。
以上的设计基本上是遵循了面向对象的设计思惟。不过,依据设计模式的原则,此中依然有能够改进的地方。
(1)根据依赖倒转原则,咱们能够定义一个接口,好比IFeature,而后基类继承于此接口,这样能够经过接口来规范基类应该实现哪些方法。
(2)咱们能够考虑使用简单工厂模式,从而进一步减小界面层类和Feature类中的耦合度。
不过,设计模式除非真有效用时再用才比较好,目前的元素设计在实际的编写代码中已经很好用了,当用到工厂类时,须要再次编写不少类出来,并且效果也不必定好。
这一章里咱们将设计矢量图层前的最后一个障碍克服了,可是,我在这个章节中仍是留下了一个没有解答的问题:地图平移后的要素重绘问题。这个问题,我会在之后的章节中专门跟你们一块儿探讨。下一章,咱们就开始走完WebGIS栅格图层和矢量图层设计这个系列的最后一站了,但愿你们持续关注。
——欢迎转载,但保留版权,请于明显处标明出处:http://www.cnblogs.com/naaoveGIS