OpenLayers技术研究参考文档.doc_第1页
OpenLayers技术研究参考文档.doc_第2页
OpenLayers技术研究参考文档.doc_第3页
OpenLayers技术研究参考文档.doc_第4页
OpenLayers技术研究参考文档.doc_第5页
已阅读5页,还剩35页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

OpenLayers项目分析(一)项目介绍(OpenLayersJavaScriptMappingLibrary)(一)项目介绍网址:/OpenLayers是由MetaCarta公司开发的,用于WebGIS客户端的JavaScript包,目前的最高版本是2.5V,通过BSDLicense发行。它实现访问地理空间数据的方法都符合行业标准,比如OpenGIS的WMS和WFS规范,OpenLayers采用纯面向对象的JavaScript方式开发,同时借用了Prototype框架和Rico库的一些组件。采用OpenLayers作为客户端不存在浏览器依赖性。由于OpenLayers采用JavaScript语言实现,而应用于Web浏览器中的DOM(文档对象模型)由JavaScript实现,同时,Web浏览器(比如IE,FF等)都支持DOM。OpenLayersAPIs采用动态类型脚本语言JavaScript编写,实现了类似与Ajax功能的无刷新更新页面,能够带给用户丰富的桌面体验(它本身就有一个Ajax类,用于实现Ajax功能)。目前,OpenLayers所能够支持的Format有:XML、GML、GeoJSON、GeoRSS、JSON、KML、WFS、WKT(Well-KnownText)。在OPenlayers.Format名称空间下的各个类里,实现了具体读写这些Format的解析器。OpenLayers所能够利用的地图数据资源“丰富多彩”,在这方面提供给拥护较多的选择,比如WMS、WFS、GoogleMap、KaMap、MSVirtualEarth、WorldWind等等。当然,也可以用简单的图片作为源。第一次使用OpenLayers:先到它的官方网站下载他的压缩包,解压后可以看到其中的一些目录和文件,拷贝目录下的OpenLayer.js、根目录下的lib目录、根目录下的img目录到你网站的Scripts目录下(当然,这个只是例子,您网站的目录结构您自己说得算,只要保证OpenLayers.js,/lib,/img在同一目录中即可)。然后,创建一个index.html作为查看地图的页面,导入OpenLayers.js和你将要创建的js。我们以加载WMS和GML文件为例。varlon=5;/x-axiscoodinateinmapunitsvarlat=40;/y-axiscoordinateinmapunitsvarzoom=5;/numberofzoomlevelsvarmap,layer;/声明变量map、layer;等同于varmap=null;varlayer=null;map=newOpenLayers.Map(map);/实例化一个地图类OpenLayers.Maplayer=newOpenLayers.Layer.WMS(OpenLayersWMS,/wms/vmap0,layers:basic);/以WMS的格式实例化图层类OpenLayers.Layermap.addLayer(layer);map.zoomToExtent(newOpenLayers.Bounds(-3.922119,44.335327,4.866943,49.553833);/在Map对象上加载Layer对象,并用map.zoomToExtent函数使地图合适地显示map.addLayer(newOpenLayers.Layer.GML(GML,gml/polygon.xml);/再在刚加载的WMS文件上,加载一GML文件剩下的工作就是,加上一些控件OpenLayers.Control之类的东西,比如LayerSwitcher等。它们会在地图浏览的“窗口”上增加一些工具栏或是“按钮”,增加互动性和功能性。当然,Openlayers中的东西远不止这些,至于它的框架分析、APIs实现机制,会在后续文章中说出。写这个的过程,也是一个学习的过程,其中难免有不妥之处,热烈欢迎大家批评指正,相互交流。(二)源代码总体结构分析通过前面的项目介绍,我们大概已经知道Openlayers是什么,能够做什么,有什么意义。接下来我们分析它怎么样,以及怎样实现的等问题。这个图是从它的文档上截取的,旨在从感官上认识一下OpenLayers的类。下面分别介绍(文档中的类是按字母顺序排列的,也按这个顺序说吧):我们看到在类的顶层“高高在上”的是OpenLayers,它为整个项目实现提供名称空间(JavaScript语言没有名称空间一说,但是它确实有自己的机制实现类似的功能,后面会说明),它直接拥有一常量VERSION_NUMBER,以标识版本。Ajax:顾名思义,用于实现Ajax功能,只是OpenLayers的开发者们把它单独写到一个类里了,其中用到了Prototype.js框架里的一些东西。同时,设计的时候也考虑了跨浏览器的问题。BaseTypes:这里定制了OpenLayers中用到的string,number和function。比如,OpenLayers.String.startsWith,用于测试一个字符串是否一以另一个字符串开头;OpenLayers.Number.limitSigDigs,用于限制整数的有效数位;OpenLayers.Function.bind,用于把某一函数绑定于对象等等。Console:OpenLayers.Console,此名称空间用于调试和把错误等输出到“控制台”上,需要结合使用./Firebug/firebug.js。Control:我们通常所说的控件类,它提供各种各样的控件,比如上节中说的图层开关LayerSwitcher,编辑工具条EditingToolbar等等。加载控件的例子:class=newOpenLayers.Map(map,controls:);map.addControl(newOpenLayers.Control.PanZoomBar();map.addControl(newOpenLayers.Control.MouseToolbar();Events:用于实现OpenLayers的事件机制。具体来说,OpenLayers中的事件分为两种,一种是浏览器事件,例如mouseup,mousedown之类的;另外一种是自定义的,如addLayer之类的。OpenLayers中的事件机制是非常值得我们学习的,后面将具体讨论。Feature:我们知道:Feature是geography和attributes的集合。在OpenLayers中,特别地OpenLayers.Feature类由一个Feature和一个lonlat组成。OpenLayers.Feature.WFS与OpenLayers.Feature.Vector继承于它。Format:此类用于读写各种格式的数据,它的子类都分别创建了各个格式的解析器。这些格式有:XML、GML、GeoJSON、GeoRSS、JSON、KML、WFS、WKT(Well-KnownText)。Geometry:怎么翻译呢,几何?是对地理对象的描述。它的子类有Collection、Curve、LinearRing、LineString、MultiLineString、MultiPoint、MultiPolygon、Point、Polygon、Rectangle、Surface,正是这些类的实例,构成了我们看到的地图。需要说明的是,Surface类暂时还没有实现。Handler:这个类用于处理序列事件,可被激活和取消。同时,它也有命名类似于浏览器事件的方法。当一个handler被激活,处理事件的方法就会被注册到浏览器监听器listener,以响应相应的事件;当一个handler被取消,这些方法在事件监听器中也会相应的被取消注册。Handler通过控件control被创建,而control通过icon表现。Icon:在计算机屏幕上以图标的形式呈现,有url、尺寸size和位置position个属性。一般情况,它与OpenLayers.Marker结合应用,表现为一个Marker。Layer:图层。Map:网业中动态地图。它就像容器,可向里面添加图层Layer和控件Control。实际上,单个Map是毫无意义的,正是Layer和Control成就了它。Marker:它的实例是OpenLayers.LonLat和OpenLayers.Icon的集合。通俗一点儿说,Icon附上一定的经纬度就是Marker。它们的组合关系是:Popup:地图上一个小巧的层,实现地图“开关”功能。使用例子:Class=newOpenLayers.Popup(chicken,newOpenLayers.LonLat(5,40),newOpenLayers.Size(200,200),examplepopup,true);map.addPopup(popup);Renderer:渲染类。在OpenLayers中,渲染功能是作为矢量图层的一个属性存在的,我们称之为渲染器,矢量图层就是通过这个渲染器提供的方法将矢量数据显示出来。以SVG和VML为例,继承关系是这样的:至于OpenLayers.Renderer.Elements为什么要存在,以及它的渲染机制,后面会说。Tile:设计这个类用于指明单个“瓦片”Tile,或者更小的分辨率。Tiles存储它们自身的信息,比如url和size等。它的类继承关系如下:Util:“跑龙套”的类。写到这里,可以看到OpenLayers的类缠绕的挺麻烦的,接下来的文章将从代码部分分析更细部的东西。(三)BaseTypes:定义底层类与定制JS内置类 先说基类型BaseTypes下,OpenLyers构建的“自己”的类。它们分别是:OpenLayers.LonLat、OpenLayers.Pixel、OpenLayers.Size、OpenLayers.Element、OpenLayers.Bounds和OpenLayers.Class。下面分别介绍:OpenLayers.LonLat:经纬度类,其实例为地图提供一经度、纬度对,即位置。有两个属性lon(x-axiscoodinate)和lat(y-axiscoordinate)。这里说明一下,怎么经纬度又与x轴坐标、y轴坐标纠缠在一起?是这样:当地图是在地理坐标投影下,它就是经纬度;不然就是地图上的xy轴坐标。除构造函数外,实现了五个函数:toShortString:function()把坐标转换为字符串;clone:function()复制一个LonLat对象;Add:function(lon,lat)改变现有地图的位置;returnnewOpenLayers.LonLat(this.lon+lon,this.lat+lat);equals:function(ll)判断传入的lon,lat对是否与当前的相等;wrapDateLine:function(maxExtent)复制下(lon,lat),指定为边界的最大范围。OpenLayers.Pixel:像素类,在显示器上以(x,y)坐标的的形式呈现像素位置。有两个属性x坐标、y坐标,提供四个成员函数:clone:function()拷贝像素;equals:function(px)判断两像素是否相等;add:function(x,y)改变(x,y)使其成为新像素;returnnewOpenLayers.Pixel(this.x+x,this.y+y);offset:function(px)调用add()使像素位置发生偏移。newPx=this.add(px.x,px.y);OpenLayers.Size:也有两个属性,宽度width、高度height。实现了两个成员函数:clone:function()和equals:function(sz)不多说了。OpenLayers.Element:在这个名称空间下,开发者写了好多API,有visible、toggle、hide、show、remove、getHeight、getDimensions和getStyle,以实现元素的显示、隐藏、删除、取得高度,取得范围等功能。以getHeight函数为例我们看看它的代码:/*APIFunction:getHeight*Parameters:*element-DOMElement*Returns:*IntegerTheoffsetheightoftheelementpassedin*/getHeight:function(element)element=OpenLayers.Util.getElement(element);returnelement.offsetHeight;这里涉及到文档对象模型DOM的一些东西,函数本身很简单,最后返回元素的高度。OpenLayers.Bounds:在这个类中,数据以四个浮点型数left,bottom,right,top的格式存储,它是一个像盒子一样的范围。它实现了三个描述一个Bound的函数:toString、toArray和toBBOX。其中,toString的代码如下:/*APIMethod:toString*Returns:*StringStringrepresentationofboundsobject.*(ex.left-bottom=(5,42)right-top=(10,45)*/toString:function()return(left-bottom=(+this.left+,+this.bottom+)+right-top=(+this.right+,+this.top+);结果类似于left-bottom=(5,42)right-top=(10,45)三个Bound数据来源函数:fromString、fromArray和fromSize;五个获取对象属性的函数:getWidth、getHeight、getSize、getCenterPixel、getCenterLonLat;余下还有:add:function(x,y),extend:function(object),containsLonLat,containsPixel,contains,intersectsBounds,containsBounds,determineQuadrant,wrapDateLine。以函数extend为例,看看源码。extend:function(object)varbounds=null;if(object)switch(object.CLASS_NAME)caseOpenLayers.LonLat:bounds=newOpenLayers.Bounds (object.lon,object.lat,object.lon,object.lat);break;caseOpenLayers.Geometry.Point:bounds=newOpenLayers.Bounds(object.x,object.y,object.x,object.y);break;caseOpenLayers.Bounds:bounds=object;break;if(bounds)if(this.left=null)|(bounds.leftthi s.left) this.left=bounds.left;if(this.bottom=null)|(bounds.bottomt his.right)this.right=bounds.right;if(this.top=null)|(bounds.topthis. top)this.top=bounds.top;可以看出,对Bounds的扩展可以有三种形式:point,lonlat,或者bounds,计算的条件是零坐标是在屏幕的左上角。OpenLayers.Class:这个类是OpenLayers中的“大红人”,只要创建其他类就得用它,同时也实现了多重继承。用法如下:单继承创建:class=OpenLayers.Class(prototype);多继承创建:class=OpenLayers.Class(Class1,Class2,prototype); 净说底层类了,对js内置类的扩展下回写。(三)BaseTypes: OpenLayers中定制JavaScript内置类OpenLayers不仅“自己”写了一些底层的类,像上回说的那些都是。同时也定制了一些JS的一些内置类,即对JS内置类的扩展。这个扩展主要包含3类:String,Number,Function,存在于BaseTypes.js文件中。String:OpenLayers对string类型定制了个方法,分别是startsWith、contains、trim和camelize;还有另外个方法:String.startsWith、String.contains、String.trim和String.Camelize,它们将会在3.0Version中被删除,可能是以前版本遗留下来的,这里就不说它们了。/Testwhetherastringstartswithanotherstring.startsWith:function(str,sub)return(str.indexOf(sub)=0);/Testwhetherastringcontainsanotherstring.contains:function(str,sub)return(str.indexOf(sub)!=-1);/Removesleadingandtrailingwhitespacecharactersfromastring.trim:function(str)returnstr.replace(/s*(.*?)s*$/,$1);/Camel-caseahyphenatedstring./Ex.chicken-headbecomeschickenHead,/and-chicken-headbecomesChickenHead./“骆驼”化带有连字符的字符串。camelize:function(str)varoStringList=str.split(-);varcamelizedString=oStringList0;for(vari=1;i0)fig=parseFloat(num.toPrecision(sig);elsefig=0;returnfig;Function:扩展了两个方法bind和bindAsEventListener(同样存在Function.bind和Function.bindAsEventListener两个被“遗弃”的函数)。/Bindafunctiontoanobject./Methodtoeasilycreateclosureswiththisaltered.bind:function(func,object)/createareferencetoallargumentspastthesecondonevarargs=Atotype.slice.apply(arguments,2);returnfunction()/Pushonanyadditionalargumentsfromtheactualfunctioncall./Thesewillcomeafterthosesenttothebindcall.varnewArgs=args.concat(Atotype.slice.apply(arguments,0);returnfunc.apply(object,newArgs);/Bindafunctiontoanobject,andconfigureittoreceivetheevent/objectasfirstparameterwhencalled.bindAsEventListener:function(func,object)returnfunction(event)returnfunc.call(object,event|window.event);这里说说这两个方法。首先看看bind方法,这是一个能够被Function的实例得到的方法,如下所示:Ftotype.bind=function()var_method=this,args=,object=arguments0;for(vari=1;iarguments.length;i+)args.push(argumentsi);returnfunction(moreargs)for(vari=0;iarguments.length;i+)args.push(argumentsi);return_method.apply(object,args);_method代表Function实例自身,bind可接收多个参数,不过它绑定是是第一个参数,该参数是一个function或者是调用环境,后面的都是执行函数的参数。Ftotype.bindAsEventListener=function(object)var_method=this;returnfunction(event)return_method.call(object,event|window.event);这里只是将object作为_method引用的环境,就是说现在可以在object对象中这样使用,object._method(event|window.event)。也许你注意到了Funtion扩展的两个方法一个用到了call而另一个用的是apply,其实这两个并没有什么太大的区别,只是参数传递的形式不同,如若没有参数要传递,那么这两个是一样的:apply(obj,argumentsArray),call(obj,arg1,arg2)。(四)空间数据的组织与实现提到数据,先思考几个问题:GIS,核心是什么?数据?平台?服务?空间数据的特征、表达方式?地理数据的模型(结构)?在OpenLayers空间数据的实现主要存在OpenLayers.Geometry类及其子类中。我们先看下面的两个图片,表现了这些类的继承关系。从图上可以清楚的看出MultiPoint、Polygon和MultiLineString这三个类实现了多重继承,即直接继承于Geometry类,又继承于Collection类(为什么要这样实现?)。OpenLyers对于Geometry对象的组织是这样的,其实最基础的就是点,然后MultiPoint由点构成,继承自Openlayers.Geometry.Collection,而LinearRing,LineString均由Point构成,Polygon由OpenLayers.Geometry.LinearRing构成。OpenLyers在解析数据时候,将所有的面、线包含的点全部都对象化为Openlayers.Geometry.Point。有人测试这里面存在问题:解析矢量数据慢,甚至在点数多的情况下,会使浏览器“崩溃”掉。想想是有道理的:OpenLyers在解析数据时候,将所有的面、线包含的点全部都对象化为点对象t,并首先将所有的对象读取到内存,得到一个Feature的集合,然后将这个集合提交给渲染器进行渲染。这样渲染起来当然慢了。至于为什么要这样,可能是OpenLayers项目本身在标准上,在框架结构上做的比较好,更细部的东西还得优化呀。可话又说回来,OpenLayers作为一个优秀的开源JS框架,学习借鉴的意义要比应用的意义大吧。下面以Point和Collection为例来说明其内部实现过程,先看Point。我们知道一个点就是一个坐标对(x,y)嘛,当然它得有两个属性x,y。在point类里,提供了六个成员函数,分别是clone、distanceTo、equals、move、rotate和resize。看看计算两点距离的函数是怎么写的:distanceTo:function(point)vardistance=0.0;if(this.x!=null)&(this.y!=null)&(point!=null)&(point.x!=null)&(point.y!=null)vardx2=Math.pow(this.x-point.x,2);vardy2=Math.pow(this.y-point.y,2);distance=Math.sqrt(dx2+dy2);returndistance;在collection集合对象中,可以存放同一类型的地理对象,也可以放不同的地理对象。定义了一个属性component,以数组对象的形式存储组成collection对象的“组件”。别的不说了,看一个获取集合大小的函数getLength:getLength:function()varlength=0.0;for(vari=0;ponents.length;i+)length+=ponentsi.getLength();returnlength;细心的朋友也许会发现,每一个基类都有一个destroy函数。它是OpenLayers实现的垃圾回收机制,以防止内存泄露,优化性能:/*APIMethod:destroy*Destroythisgeometry.*/destroy:function()ponents.length=0;ponents=null;。(五)OpenLayers数据解析以GML为例前面也提到过,OpenLayers设计是符合标准的,有良好的框架结构和实现机制,非常值得学习。OpenLayers支持的格式比较多,有XML、GML、GeoJSON、GeoRSS、JSON、KML、WFS等。这回主要以GML为例来看OpenLayers数据的解析过程。先来了解一下GML:GML(GeographyMarkupLanguage)即地理标识语言,它由OGC(开放式地理信息系统协会)于1999年提出,目前版本是3.0。GML是XML在地理空间信息领域的应用。利用GML可以存储和发布各种特征的地理信息,并控制地理信息在Web浏览器中的显示。地理空间互联网络作为全球信息基础架构的一部分,已成为Internet上技术追踪的热点。许多公司和相关研究机构通过Web将众多的地理信息源集成在一起,向用户提供各种层次的应用服务,同时支持本地数据的开发和管理。GML可以在地理空间Web领域完成了同样的任务。GML技术的出现是地理空间数据管理方法的一次飞跃。介绍一篇文章:GML30的WebGlS研究。我们从总体上来把握一下OpenLayers对于GML数据的解析,首先通过调用得到GML文本数据,然后通过Formate.GML类的read方法来解析这个文本,解析得到Geometry对象,然后Geometry对象用相应的渲染器画出来。其实解析得到还是那些基本的Point呀、LineString呀之类的Geometry对象,就是我们在地图上看到的那些内容。下面看其实现过程:/read()函数读取数据,获取特征列表read:function(data)if(typeofdata=string)data=OpenLayers.Format.XML.prototype.read.apply(this,data);varfeatureNodes=this.getElementsByTagNameNS(data.documentElement,this.gmlns,this.featureName);varfeatures=;for(vari=0;ifeatureNodes.length;i+)varfeature=this.parseFeature(featureNodesi);if(feature)features.push(feature);returnfeatures;/函数parseFeature()是OpenLayers中GML数据格式解析的核心,就是它创建地理对象/和其属性。/实际上,每一个Foramt子类都实现了这个成员函数,完成类似的功能。parseFeature:function(node)/onlyacceptongeometryperfeature-lookforhighestordervarorder=MultiPolygon,Polygon,MultiLineString,LineString,MultiPoint,Point;vartype,nodeList,geometry,parser;for(vari=0;i0)/onlydealwithfirstgeometryofthistypevarparser=this.parseGeometrytype.toLowerCase();if(parser)geometry=parser.apply(this,nodeList0);elseOpenLayers.Console.error(Unsupportedgeometrytype:+type);/stoplookingfordifferentgeometrytypesbreak;/constructfeature(optionallywithattributes)varattributes;if(this.extractAttributes)attributes=this.parseAttributes(node);varfeature=newOpenLayers.Feature.Vector(geometry,attributes);/assignfid-thiscancomefromafidoridattributevarchildNode=node.firstChild;varfid;while(childNode)if(childNode.nodeType=1)fid=childNode.getAttribute(fid)|childNode.getAttribute(id);if(fid)break;childNode=childNode.nextSibling;feature.fid=fid;returnfeature;剩下就是由具体的函数parseandbulid基本的地理对象(还有Attribute),包括point、multipoint、linestring、multilinestring、polygon、multipolygon等,然后在write出来。结合前面的“OpenLayers空间数据的组织”,我们可以看到OpenLayers在解析获取GML数据的时候,比如涉及到面、线的时候,总是以点为基础构建的。有的朋友做过测试,说这时候,直接用SVG画出来,性能上会好很多(具体没测试过,不想多说什么)。(六)数据渲染分析实际上,OpenLayers的整个表现过程是这样的:通过调用获取数据,然后各种格式的解析器解析数据,在用所谓的渲染器渲染后加到图层上,最后再结合相应的控件表现出来,成为一幅我们看到的“动态”地图。这里主要讨论OpenLayers.Renderer这个类及其子类。Renderer类提供了一些虚方法,以供其子类继承,像setExtent、drawFeature、drawGeometry、eraseFeatures、eraseGeometry等。Elements继承Renderer,具体实现渲染的类又继承Renderer类。之所以这样设计,是因为不同的矢量格式数据需要共享相应的函数,在Elements这个类中封装一下。这个类的核心是drawGeometry和drawGe

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论