`

Geoserver & Openlayers 学习笔记

 
阅读更多

Geoserver简介

Geoserver是一个功能齐全,遵循 OGC开放标准的开源 WFS-T WMS服务器。利用 Geoserver可以把数据作为 maps/images来发布 (利用 WMS来实现 )也可以直接发布实际的数据 (利用 WFS来实现 ),同时也提供了修改,删除和新增的功能 (利用 WFS-T)

 

GeoServer, 顾名思义 ,是一个 Server. 它是开源的 ,允许用户查看和编辑地理数据。这是地理信息系统 (GIS) 领域。 GeoServer 是符合 OGC 规范的一个全功能的 WFS-T WMS  server

 

GeoServer能够发布的数据类型:

地图或影象——应用 WMS

实时数据——应用 WFS

用户更新、删除和编辑的数据——应用 WFS-T

 

相关概念的:

WMS: Web Map Service Web地图服务

利用具有地理空间位置信息的数据制作地图。其中将地图定义为地理数据可视的表现。这个规范定义了三个操作:

GetCapabitities 返回服务级元数据,它是对服务信息内容和要求参数的一种描述;

GetMap 返回一个地图影像,其地理空间参考和大小参数是明确定义了的;

GetFeatureInfo(可选)返回显示在地图上的某些特殊要素的信息

 

WFS: Web Feature Service Web要素服务)

Web 地图服务返回的是图层级 的地图影像,

Web要素服务( WFS)返回的是要素级的 GML 编码 ,并提供对要素的增加、修改、删除 等事务操作,是对 Web地图服务的进一步深入。 OGC Web 要素服务允许客户端从多个 Web要素服务中取得使用地理标记语言( GML)编码的地理空间数据,定义了五个操作:

GetCapabilites    返回 Web要素服务性能描述文档(用 XML描述);

DescribeFeatureType    返回描述可以提供服务的任何要素 结构的 XML文档;

GetFeature    一个获取要素实例的请求提供服务;

Transaction    为事务请求提供服务;

LockFeature    处理在一个事务期间对一个或多个要素类型实例上锁的请求。

 

WFS-T : Web Map Service-Transactional. 允许用户以可传输的块编辑地理数据。

 

WCS Web Coverage Service Web 覆盖服务)

Web 覆盖服务( WCS)面向空间影像数据 ,它将包含地理位置值的地理空间数据作为覆盖( Coverage在网上相互交换。

网络覆盖服务由三种操作组成: GetCapabilities GetCoverage DescribeCoverageType

GetCapabilities 操作返回描述服务 和数据集的 XML文档。

GetCoverage操作是在 GetCapabilities确定什么样的查询可以执行、什么样的数据能够获取之后执行的,它使用通用的覆盖格式返回地理位置的值或属性。

DescribeCoverageType 操作允许客户端请求由具体的 WCS服务器提供的任一覆盖层的完全描述。

 

GML: Geography Markup Language. 一种用于描述地理数据的 XML

 

OGC——Open Geospatial Consortium—— 开放地理信息联盟

 

总之 GeoServer 是您需要显示地图在网页的那些工具的当中一个,用户可以缩放并且移动。可以与一些客户端联合使用,比如: MapBuilder (for web pages), UDig, GVSig,等等。 对标准的使用允许信息从 GeoServer 到其它地理信息可以很容易地被结合。

5d2a1bd81412813733fa1c2b.jpg.gif

如果你对 GeoServer发出一个 WMS请求,你就可能得到如下的一张图:

 

查看 Demo

welcome界面中单击 demo page链接,进入页面后单击 WFS-T 链接就可以启动一个名叫 MapBuilder的基于 Javascript 的地图地图编辑器。启动 MapBuilder后我们可以看到一张样图,那就就从它开始吧!用其提供的工具对图进行修改。自己练习。

 

关于 geoserver开发

geoserver只能用 j2ee开发

geoserver是符合 ogc   wms/wfs/wcs 标准的地图服务器,建设一套完整的 webgis系统还需要客户端配合, mapbuilder openlayers 是非常好的两个选择。对于较大的项目,空间数据库也是必不可少的, geoserver支持商业的 oracle db2,开源的 postgis mysql

扯得更远一点, geoserver支持 google   map google   earth

 

Geotools

外文官网 http://geotools.codehaus.org/

 

Geotools是开源的 Java代码库,在 GIS中提供对地理空间数据的标准操作。简单说,它就是一个中间件,提供的功能符合 OGC规范,且与 GeoAPI有密切的联系。它支持的数据格式有 Shapefile GML WFS PostGIS Oracle Spatial ArcSDE MySQL GeoMedia MapInfo等。

利用 Geotools能够实现:

格网覆盖 Grid coverages——栅格数据,

坐标系统转换 Coordinate Transformation

数据渲染 Renderers

格式化 Styling——符号化数据集等功能。

 

WFS地址

把下面地址中的 HighwayInterchange改成自己创建的 featuretype的名字,在浏览器中查看, WFS URL

 

http://localhost:8080/geoserver/wfs?request=getfeature&service=wfs&version=1.0.0&typename=States

 

 

下面地址的 youtian改成自己的 FeatureType名字,就是自己的 WFS地址

 

http://localhost:8080/geoserver/wms/kml_reflect?layers=youtian

 

 

Openlayers dom结构

 

OpenLayers项目分析——(一)项目介绍

(OpenLayers JavaScript Mapping Library)

 

(一)项目介绍

网址: http://www.openlayers.org/

 

   OpenLayers 是由 MetaCarta公司开发的,用于 WebGIS客户端的 JavaScript包,目前的最高版本是 2.5 V,通过 BSD License 发行。它实现访问地理空间数据的方法都符合行业标准,比如 OpenGIS WMS WFS规范, OpenLayers采用纯面向对象的 JavaScript方式开发,同时借用了 Prototype框架和 Rico库的一些组件。

 

  采用 OpenLayers作为客户端不存在浏览器依赖性。由于 OpenLayers采用 JavaScript语言实现,而应用于 Web浏览器中的 DOM(文档对象模型)由 JavaScript实现,同时, Web浏览器(比如 IE FF等)都支持 DOM

 

   OpenLayers APIs 采用动态类型脚本语言 JavaScript编写,实现了类似与 Ajax功能的无刷新更新页面,能够带给用户丰富的桌面体验(它本身就有一个 Ajax类,用于实现 Ajax功能)。

 

  目前, OpenLayers所能够支持的 Format有: XML GML GeoJSON GeoRSS JSON KML WFS WKT(Well-Known Text)。在 OPenlayers.Format名称空间下的各个类里,实现了具体读/写这些 Format的解析器。

 

   OpenLayers所能够利用的地图数据资源“丰富多彩”,在这方面提供给拥护较多的选择,比如 WMS WFS GoogleMap KaMap MSVirtualEarth WorldWind等等。当然,也可以用简单的图片作为源。

 

第一次使用 OpenLayers

 

  先到它的官方网站 http://www.openlayers.org下载他的压缩包,解压后可以看到其中的一些目录和文件,拷贝目录下的 OpenLayer.js 、根目录下的 lib 目录、根目录下的 img 目录到你网站的 Scripts 目录下 (当然,这个只是例子,您网站的目录结构您自己说得算,只要保证 OpenLayers.js /lib /img在同一目录中即可)。 然后,创建一个 index.html作为查看地图的页面,导入 OpenLayers.js和你将要创建的 js

 

  我们以加载 WMS GML文件为例。 

 

    <script src="../lib/OpenLayers.js"></script>

   <script type="text/javascript">

        var lon = 5;    //x-axis coodinate in map units

        var lat = 40;   //y-axis coordinate in map units

        var zoom = 5;   //number of zoom levels

        var map, layer;      // 声明变量 map layer;等同于 var map = null; var layer = null;

 

        map = new OpenLayers.Map('map');

        // 实例化一个地图类 OpenLayers.Map

 

        layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",

                    "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );

        // WMS的格式实例化图层类 OpenLayers.Layer

 

        map.addLayer(layer);

        map.zoomToExtent(newOpenLayers.Bounds(-3.922119,44.335327,

        4.866943,49.553833));

     // Map对象上加载 Layer对象,并用 map.zoomToExtent函数使地图合适地显示

 

     map.addLayer(new OpenLayers.Layer.GML("GML", "gml/polygon.xml"));

     //再在刚加载的 WMS文件上,加载一 GML文件

 

  剩下的工作就是,加上一些控件 OpenLayers.Control之类的东西,比如 LayerSwitcher等。它们会在地图浏览的“窗口”上增加一些工具栏或是“按钮”,增加互动性和功能性。

 

  当然, Openlayers中的东西远不止这些,至于它的框架分析、 APIs实现机制,会在后续文章中说出。写这个的过程,也是一个学习的过程,其中难免有不妥之处,热烈欢迎大家批评指正,相互交流。

 

OpenLayers 项目完整分析——(二)源代码总体结构分析

(二)源代码总体结构分析

 

通过前面的项目介绍,我们大概已经知道 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 = new OpenLayers.Map('map', { controls: [] });

     map.addControl(new OpenLayers.Control.PanZoomBar());

     map.addControl(new OpenLayers.Control.MouseToolbar());

 

   Events :用于实现 OpenLayers 的事件机制。 具体来说, OpenLayers中的事件分为两种,一种是浏览器事件 ,例如 mouseup,mousedown之类的;另外一种是自定义的 ,如 addLayer之类的。 OpenLayers中的事件机制是非常值得我们学习的,后面将具体讨论。

 

   Feature :我们知道: Feature geography attributes 的集合 。在 OpenLayers中,特别地 OpenLayers.Feature 类由一个 marker 和一个 lonla 组成 OpenLayers. Feature.WFS OpenLayers. Feature. Vector继承于它。

 

   Format :此类用于读/写各种格式的数据,它的子类都分别创建了各个格式的解析器 。这些格式有: XML GML GeoJSON GeoRSS JSON KML WFS WKT(Well-Known Text)

 

   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 3个属性。一般情况,它 OpenLayers.Marker 结合应用 表现为一个 Marker

 

   Layer :图层

 

   Map 网页中动态地图 。它就像容器,可向里面添加图层 Layer 和控件 Control 。实际上,单个 Map是毫无意义的,正是 Layer Control成就了它。

 

   Marker :它的实例是 OpenLayers.LonLat OpenLayers.Icon的集合。通俗一点儿说, Icon 附上一定的经纬度就是 Marker

 

   Popup 地图上一个小巧的层,实现地图“开关”功能 。使用例子:

 

       Class = new OpenLayers.Popup("chicken",

                   new OpenLayers.LonLat(5,40),

                   new OpenLayers.Size(200,200),

                   "example popup",

                   true);

       map.addPopup(popup);

 

   Renderer :渲染类 。在 OpenLayers中,渲染功能是作为矢量图层的一个属性存在的,我们称之为渲染器,矢量图层就是通过这个渲染器提供的方法将矢量数据显示出来。以 SVG VML为例,继承关系是这样的:    

至于 OpenLayers. Renderer. Elements为什么要存在,以及它的渲染机制,后面会说。

 

   Tile :设计这个类用于指明单个“瓦片” Tile ,或者更小的分辨率 Tiles存储它们自身的信息,比如 url size等。它的类继承关系如下:

 

   Util :“跑龙套”的类。

 

  写到这里,可以看到 OpenLayers 的类缠绕的挺麻烦的,接下来的文章将从代码部分分析更细部的东西。

 

OpenLayers 项目分析——(三) BaseTypes

(三) BaseTypes :定义底层类与定制 JS内置类  

 

    先说基类型 BaseTypes下, OpenLyers构建的“自己”的类。它们分别是: OpenLayers. LonLat OpenLayers. Pixel OpenLayers.Size OpenLayers. Element OpenLayers. Bounds OpenLayers. Class。下面分别介绍:

 

   OpenLayers. LonLat :经纬度类,其实例为地图提供一经度、纬度对,即位置 。有两个属性 lon x-axis coodinate )和 lat y-axis coordinate 。这里说明一下,怎么经纬度又与 x轴坐标、 y轴坐标纠缠在一起?是这样:当地图是在地理坐标投影下,它就是经纬度;不然就是地图上的 x y轴坐标。除构造函数外,实现了五个函数:

 

toShortString:function() 把坐标转换为字符串;

clone:function()  复制一个 LonLat对象;

 

Add:function(lon,lat)  改变现有地图的位置;

   return new OpenLayers.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)使其成为新像素;

return new OpenLayers.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:

     * {Integer} The offset height of the element passed in

     */

 

    getHeight: function(element) {

        element = OpenLayers.Util.getElement(element);

        return element.offsetHeight;

    }

这里涉及到文档对象模型 DOM的一些东西,函数本身很简单,最后返回元素的高度。

 

 

   OpenLayers. Bounds :在这个类中,数据以四个浮点型数 left, bottom, right, top 的格式存储 ,它是一个像盒子一样的范围。它实现了三个描述一个 Bound的函数: toString toArray toBBOX。其中, toString的代码如下:

 

   /**

     * APIMethod: toString

     *

     * Returns:

     * {String} String representation of bounds object.

     *          (ex.<i>"left-bottom=(5,42) right-top=(10,45)"</i>)

     */

    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) {

        var bounds = null;

        if (object) {

            switch(object.CLASS_NAME) {

                case "OpenLayers.LonLat":   

                    bounds = new OpenLayers.Bounds    (object.lon, object.lat, object.lon, object.lat);

                    break;

                case "OpenLayers.Geometry.Point":

                    bounds = new OpenLayers.Bounds(object.x, object.y,object.x, object.y);

                    break;                

 

                case "OpenLayers.Bounds":  

                    bounds = object;

                    break;

            }

            if (bounds) {

                if ( (this.left == null) || (bounds.left < this.left)) {

                     this.left = bounds.left;}

 

                if ( (this.bottom == null) || (bounds.bottom <                     this.bottom) ) {

                    this.bottom = bounds.bottom;}

 

                if ( (this.right == null) || (bounds.right > this.right) ) {

                    this.right = bounds.right;}

 

                if ( (this.top == null) || (bounds.top > this.top) ) {

                    this.top = bounds.top;}

            }

        }

    }

 

可以看出,对 Bounds的扩展可以有三种形式: point, lonlat, 或者 bounds,计算的条件是零坐标是在屏幕的左上角。

 

 

   OpenLayers. Class :这个类是 OpenLayers 中的“大红人”,只要创建其他类就得用它,同时也实现了多重继承。用法如下:

 

  单继承创建: class = OpenLayers.Class(prototype);

  多继承创建: class = OpenLayers.Class(Class1, Class2, prototype);

 

    净说底层类了,对 js内置类的扩展下回写。

 

 

OpenLayers 项目分析——(三) BaseTypes ( )

(三) BaseTypes OpenLayers中定制 JavaScript内置类

 

   OpenLayers不仅“自己”写了一些底层的类,像上回说的那些都是。同时也定制了一些 JS的一些内置类,即对 JS内置类的扩展。这个扩展主要包含 3类: String Number Function 存在于 BaseTypes.js文件中。

 

   String OpenLayers string类型定制了8个方法,分别是 startsWith contains trim camelize;还有另外4个方法: String. startsWith String. contains String.trim String. Camelize,它们将会在 3.0Version中被删除,可能是以前版本遗留下来的,这里就不说它们了。

 

   //Test whether a string starts with another string.

   startsWith: function(str, sub) {

    return (str.indexOf(sub) == 0);

    }

 

   //Test whether a string contains another string.

    contains: function(str, sub) {

        return (str.indexOf(sub) != -1);

    }

 

    //Removes leading and trailing whitespace characters from a string.

    trim: function(str) {

        return str.replace(/^"s*(.*?)"s*$/, "$1");   

    }

 

   //Camel-case a hyphenated string.

  //Ex."chicken-head"becomes"chickenHead",

   //and"-chicken-head"becomes"ChickenHead".

   // “骆驼”化带有连字符的字符串。

   camelize: function(str) {

        var oStringList = str.split('-');

        var camelizedString = oStringList[0];

        for (var i = 1; i < oStringList.length; i++) {

            var s = oStringList[i];

            camelizedString += s.charAt(0).toUpperCase() + s.substring(1);

        }

        return camelizedString;

    }

 

Number

项目仅对 number类型扩展了一个方法 OpenLayers. Number. limitSigDigs (还有一个方法 Number. limitSigDigs ,同样在 3.0中会删除)。

    //Limit the number of significant digits on an integer.

    limitSigDigs: function(num, sig) {

        var fig;

        if(sig > 0) {

            fig = parseFloat(num.toPrecision(sig));

        } else {

            fig = 0;

        }

        return fig;

    }

 

Function

扩展了两个方法 bind bindAsEventListener(同样存在 Function.bind Function. bindAsEventListener两个被“遗弃”的函数)。

 

    //Bind a function to an object. 

    //Method to easily create closures with'this' altered.

    bind: function(func, object) {

        // create a reference to all arguments past the second one

        var args = Array.prototype.slice.apply(arguments, [2]);

        return function() {

            // Push on any additional arguments from the actual function call.

            // These will come after those sent to the bind call.

            var newArgs = args.concat(

                Array.prototype.slice.apply(arguments, [0])

            );

            return func.apply(object, newArgs);

        }

    }

 

    //Bind a function to an object, and configure it to receive the event

    //object as first parameter when called.

    bindAsEventListener: function(func, object) {

        return function(event) {

            return func.call(object, event || window.event);

        };

    }

 

这里说说这两个方法。

首先看看 bind方法,这是一个能够被 Function的实例得到的方法,如下所示:

Function.prototype.bind = function() {

var _method = this, args = [], object = arguments[0];

for (var i = 1; i < arguments.length; i++)

args.push(arguments[i]);

return function(moreargs) {

for (var i = 0; i < arguments.length; i++)

args.push(arguments[i]);

return _method.apply(object, args);

}

};

 

_method 代表 Function实例自身, bind可接收多个参数,不过它绑定是是第一个参数,该参数是一个 function或者是调用环境,后面的都是执行函数的参数。

 

 

Function.prototype.bindAsEventListener = function(object) {

var _method = this;

return function(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 ]])

 

OpenLayers项目分析——(四)空间数据的组织与实现

 

提到数据,先思考几个问题:

   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) {

        var distance = 0.0;

        if ( (this.x != null) && (this.y != null) &&

             (point != null) && (point.x != null) && (point.y != null) ) {            

             var dx2 = Math.pow(this.x - point.x, 2);

             var dy2 = Math.pow(this.y - point.y, 2);

             distance = Math.sqrt( dx2 + dy2 );

        }

        return distance;

    }

 

  在 collection集合对象中,可以存放同一类型的地理对象,也可以放不同的地理对象。定义了一个属性 component ,以数组对象的形式存储组成 collection对象的“组件”。别的不说了,看一个获取集合大小的函数 getLength

 

    getLength: function() {

        var length = 0.0;

        for (var i = 0; i < this.components.length; i++) {

            length += this.components[i].getLength();

        }

        return length;

    }

 

  细心的朋友也许会发现,每一个基类都有一个 destroy函数。它是 OpenLayers实现的垃圾回收机制,以防止内存泄露,优化性能:

 

   /* APIMethod: destroy

     * Destroy this geometry.

     */

    destroy: function () {

        this.components.length = 0;

        this.components = null;

    }

 

 

OpenLayers项目分析——(五) 数据解析——以 GML为例

(五) OpenLayers 数据解析—以 GML为例

 

  前面也提到过, OpenLayers设计是符合标准的,有良好的框架结构和实现机制,非常值得学习。 OpenLayers支持的格式比较多,有 XML GML GeoJSON GeoRSS JSON KML WFS等。这回主要以 GML为例来看 OpenLayers 数据的解析过程。

 

  先来了解一下 GML

   GML (Geography Markup Language) 即地理标识语言,它由 OGC(开放式地理信息系统协会)于 1999年提出,目前版本是 3.0 GML XML在地理空间信息领域的应用。利用 GML可以存储和发布各种特征的地理信息,并控制地理信息在 Web浏览器中的显示。地理空间互联网络作为全球信息基础架构的一部分,已成为 Internet上技术追踪的热点。许多公司和相关研究机构通过 Web将众多的地理信息源集成在一起,向用户提供各种层次的应用服务,同时支持本地数据的开发和管理。 GML可以在地理空间 Web领域完成了同样的任务。 GML技术的出现是地理空间数据管理方法的一次飞跃。

  介绍一篇文章: GML3 0 WebGlS研究。

 

  我们从总体上来把握一下 OpenLayers 对于 GML 数据的解析,首先通过调用得到 GML 文本数据,然后通过 Formate.GML 类的 read 方法来解析这个文本,解析得到 Geometry 对象,然后 Geometry 对象用相应的渲染器画出来 。其实解析得到还是那些基本的 Point呀、 LineString呀之类的 Geometry对象,就是我们在地图上看到的那些内容。

 

  下面看其实现过程:

 

   //read()函数读取数据,获取特征列表

    read: function(data) {

        if(typeof data == "string") {

            data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);

        }

        var featureNodes = this.getElementsByTagNameNS   (data.documentElement,this.gmlns,   this.featureName);

        var features = [];

        for(var i=0; i<featureNodes.length; i++) {

            var feature = this.parseFeature(featureNodes[i]);

            if(feature) {

                features.push(feature);

            }

        }

        return features;

    }

 

  //函数 parseFeature() OpenLayers GML数据格式解析的核心,就是它创建地理对象 

    // 和其属性。                

   //实际上,每一个 Foramt 子类都实现了这个成员函数,完成类似的功能。

    parseFeature: function(node) {

        // only accept on geometry per feature - look for highest "order"

        var order = ["MultiPolygon", "Polygon",

                     "MultiLineString", "LineString",

                     "MultiPoint", "Point"];

        var type, nodeList, geometry, parser;

        for(var i=0; i<order.length; ++i) {

            type = order[i];

            nodeList = this.getElementsByTagNameNS(node, this.gmlns, type);

            if(nodeList.length > 0) {

                // only deal with first geometry of this type

                var parser = this.parseGeometry[type.toLowerCase()];

                if(parser) {

                    geometry = parser.apply(this, [nodeList[0]]);

                } else {

                    OpenLayers.Console.error("Unsupported geometry type: " +

                                             type);

                }

                // stop looking for different geometry types

                break;

            }

        }       

        // construct feature (optionally with attributes)

        var attributes;

        if(this.extractAttributes) {

            attributes = this.parseAttributes(node);

        }

        var feature = new OpenLayers.Feature.Vector(geometry, attributes);

        // assign fid - this can come from a "fid" or "id" attribute

        var childNode = node.firstChild;

        var fid;

        while(childNode) {

            if(childNode.nodeType == 1) {

                fid = childNode.getAttribute("fid") ||

                      childNode.getAttribute("id");

                if(fid) {

                    break;

                }

            }

            childNode = childNode.nextSibling;

        }

        feature.fid = fid;

        return feature;

    }

 

  剩下就是由具体的函数 parse and   bulid基本的地理对象(还有 Attribute),包括 point multipoint linestring multilinestring polygon multipolygon等,然后在 write出来。

 

  结合前面的“ OpenLayers空间数据的组织”,我们可以看到 OpenLayers在解析获取 GML数据的时候,比如涉及到面、线的时候,总是以点为基础构建的。有的朋友做过测试,说这时候,直接用 SVG画出来,性能上会好很多(具体没测试过,不想多说什么)。

 

 

OpenLayers项目分析——(六)数据渲染分析

(六)数据渲染分析

实际上, OpenLayers的整个表现过程是这样的:通过调用获取数据,然后各种格式的解析器解析数据,在用所谓的渲染器渲染后加到图层上,最后再结合相应的控件表现出来,成为一幅我们看到的“动态”地图。

 

  这里主要讨论 OpenLayers. Renderer 这个类及其子类。

   Renderer类提供了一些虚方法,以供其子类继承,像 setExtent drawFeature drawGeometry eraseFeatures eraseGeometry等。

 

   Elements继承 Renderer,具体实现渲染的类又继承 Renderer类。之所以这样设计,是因为不同的矢量格式数据需要共享相应的函数,在 Elements这个类中封装一下。这个类的核心是 drawGeometry drawGeometryNode两个函数。其中 drawGeometry调用了 drawGeometryNode,创建出基本的地理对象。

 

    drawGeometry: function(geometry, style, featureId) {

        var className = geometry.CLASS_NAME;

        if ((className == "OpenLayers.Geometry.Collection") ||

            (className == "OpenLayers.Geometry.MultiPoint") ||

            (className == "OpenLayers.Geometry.MultiLineString") ||

            (className == "OpenLayers.Geometry.MultiPolygon")) {

            for (var i = 0; i < geometry.components.length; i++) {

                this.drawGeometry(geometry.components[i], style, featureId);

            }

            return;

        };

 

        //first we create the basic node and add it to the root

        var nodeType = this.getNodeType(geometry);

        var node = this.nodeFactory(geometry.id, nodeType, geometry);

        node._featureId = featureId;

        node._geometryClass = geometry.CLASS_NAME;

        node._style = style;

        this.root.appendChild(node);

       

        //now actually draw the node, and style it

        this.drawGeometryNode(node, geometry);

    }

 

  渲染器的继承关系这样的:

  具体实现渲染的方法在 OpenLayers. Renderer.SVG OpenLayers. Renderer.VML 两个类中实现的,就是实现 Elements提供的虚方法,比如 drawPoint drawCircle drawLineString drawLinearRing drawLine drawPolygon drawSurface等。以 drawCircle为例看看具体的实现过程:

 

    drawCircle: function(node, geometry, radius) {

        if(!isNaN(geometry.x)&& !isNaN(geometry.y)) {

            var resolution = this.getResolution();

            node.style.left = (geometry.x /resolution).toFixed() - radius;

            node.style.top = (geometry.y /resolution).toFixed() - radius;

            var diameter = radius * 2;

            node.style.width = diameter;

            node.style.height = diameter;

        }

    }

 

OpenLayers项目分析——(七)地图表现

(七)地图表现

        一开始看到 OpenLayers,就有一个问题。就是它作为 WebGIS的前端,通俗地说,是“显示”地图的。那么,它显示的地图是什么,是怎么显示的,又是怎么实现的?——暂且把这个问题叫做地图表现。我觉得最关键的就是 Map 类,把这个类分析清楚了,问题就解决了一大半了。

 

  前面第一回里说过怎么实例化一个地图,怎么向地图里加图层加控件。其实,地图是这样的,它就像一个容器,可以盛东西。要分析它光理解这些还不够,我们要知道这个容器是怎么做出来的,及具体都有什么功能。

 

   Map类有两个常量: Z_INDEX_BASE EVENT_TYPES,不说了,可顾名而思其意。再看它定义的一些属性: div The element that contains the map)、 baseLayer The currently selected base layer)、 events An events object that handles all events on the map )。是这样, web页的 div通过以 id name的形式获得 map对象,然后 layers control在加载到 map上,表现为地图。顺便说一句,控件 control和事件 event是相关联的,这以后会说。

 

  OpenLayers.Map类提供了两种实例化方式,举例来看:

 

   // create a map with default options in an element with the id "map1"

     var map = new OpenLayers.Map("map1");

 

     // create a map with non-default options in an element with id "map2"

//Optional object with properties to tag onto the map.

     var options = {

          maxExtent: new OpenLayers.Bounds(-200000, -200000, 200000, 200000),

          maxResolution: 156543,

          units: 'meters',

          projection: "EPSG:41001"

      };

      var map = new OpenLayers.Map("map2", options);

 

    OpenLayers.Map类实现的函数 APIMethod是分组的,比如 Layer Functions Control Functions Popup Functions Container Div Functions Zoom, Center, Pan Functions Layer Options Baselayer Functions Zooming Functions Translation Functions。其中,最关键的是 Layer Functions Control Functions,因为就是 Layer对象和 Control对象构成了 map的主体。下面从每组函数中挑选出一两个来,看看具体实现过程。

 

   Layer Functions

 

就看 addLayer函数吧,下面的 addLayers就是调用的它,代码如下:

 

    addLayer: function (layer) {

        for(var i=0; i < this.layers.length; i++) {

            if (this.layers[i] == layer) {

                var msg = "You tried to add the layer: " + layer.name +

                          " to the map, but it has already been added";

                OpenLayers.Console.warn(msg);

                return false;

            }

        }           

 

        layer.div.style.overflow = "";

        this.setLayerZIndex(layer, this.layers.length);

 

        if (layer.isFixed) {

            this.viewPortDiv.appendChild(layer.div);

        } else {

            this.layerContainerDiv.appendChild(layer.div);

        }

 

        this.layers.push(layer);

        layer.setMap(this);

 

        if (layer.isBaseLayer) {

            if (this.baseLayer == null) {

                // set the first baselaye we add as the baselayer

                this.setBaseLayer(layer);

            } else {

                layer.setVisibility(false);

            }

        } else {

            layer.redraw();

        }

 

        this.events.triggerEvent("addlayer");

    }

 

可以看到其中涉及到 layer的一些方法,下一回具体介绍 OpenLayers. Layer类。

   Control Functions

    addControl: function (control, px) {

        this.controls.push(control);

        this.addControlToMap(control, px);

    }

 

可以看出,添加控件的过程是由 controls.Push() addControlToMap()两个函数共同完成的。

    addControlToMap: function (control, px) {

        // If a control doesn't have a div at this point, it belongs in the

        // viewport.

        control.outsideViewport = (control.div != null);

        control.setMap(this);

        var div = control.draw(px);

        if (div) {

            if(!control.outsideViewport) {

                div.style.zIndex = this.Z_INDEX_BASE['Control'] +

                                    this.controls.length;

                this.viewPortDiv.appendChild( div );

            }

        }

    }

 

    Popup Functions:这组函数和上两组函数相似,是在地图上添加或删除 Popup 对象。

 

   Zoom, Center, Pan Functions

     //Allows user to pan by a value of screen pixels

       pan: function(dx, dy) {

 

        // getCenter

        var centerPx = this.getViewPortPxFromLonLat(this.getCenter());

 

        // adjust

        var newCenterPx = centerPx.add(dx, dy);

       

        // only call setCenter if there has been a change

        if (!newCenterPx.equals(centerPx)) {

            var newCenterLonLat = this.getLonLatFromViewPortPx(newCenterPx);

            this.setCenter(newCenterLonLat);

        }

   }

 

  Zooming Functions:

这里就看看放大缩小函数吧。

    zoomIn: function() {

        this.zoomTo(this.getZoom() + 1);

    }

 

    zoomOut: function() {

        this.zoomTo(this.getZoom() - 1);

    }

 

显然, zoomIn zoomOut都使用了 getZoom方法,放大就是让 zoom加1,缩小减1。

 

OpenLayers项目分析——(八)地图表现(续)

(八)地图表现(续)

 

  上一回说到 OpenLayers.Map类,这回介绍组成 Map的主体部分 OpenLayers. Layer类,先从其实现细节上分析,看它是怎么设计出来的。关于它许许多多的子类,即各种图层,想单独写一篇。

 

   OpenLayers. Layer 提供了一个 EVENT_TYPES常量,用于支持关于图层的应用事件类型,这些事件有 "loadstart", "loadend", "loadcancel", "Visibilitychanged"

 

  它“固有”的3个属性: id,name,div。其中, id name layer的身份,在对图层进行操作的时候,就是用它们标志的。至于 div,大家都制知道, DOM元素,用于存放图层。

 

  定义的 map event属性,是图层对象对 map event对象的引用; projection属性,设置默认情况下,地图的投影,同时也设置 maxExtent, maxResolution, units

 

  来看看构造函数:

 

     * name - {String} The layer name

     * options - {Object} Hashtable of extra options to tag onto the layer

     */

    initialize: function(name, options) {

        this.addOptions(options);

        this.name = name;

        if (this.id == null) {

            this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");

            this.div = OpenLayers.Util.createDiv();

            this.div.style.width = "100%";

            this.div.style.height = "100%";

            this.div.id = this.id;

            this.events = new OpenLayers.Events(this, this.div,

                                                this.EVENT_TYPES);

        }

        if (this.wrapDateLine) {

            this.displayOutsideMaxExtent = true;

        }

    }

 

OpenLayers中每一个类的构造函数都是以 initialize命名的。

 

  再看看其成员函数:

   destroy函数,相当于析构函数;

   onMapResize removeMap 虚函数,提供给子类继承;

 

   //移动函数

   moveTo:function(bounds, zoomChanged, dragging) {

        var display = this.visibility;

        if (!this.isBaseLayer) {

            display = display && this.inRange;

        }

        this.display(display);

    }

 

  下面一组函数是 Baselayer Functions 函数,就是 layer Baselayer 的话,所用的函数。

 

比如, initResolutions getResolution getExtent等。

 

  通过这两次的分析,可以发现, Map Layers的关系:它们是相互引用的。实际上是这样, OpenLayers Map类主要包含了对每个图层的引用,对每个控件的引用,对事件的引用,对装载容器的引用(其实就是那些 map上层的 div)以及对 pop的引用,而其自身又包含有大量的方法和属性。图层主要包含了对 map的引用,对自身 div容器的引用以及事件的引用,而图层自身又包含了大量的属性和方法。 map引用了 layer,而 layer又引用了 map,这里就直接形成了循环引用关系。

 

  这样的组成和关联关系,每动一下,就会涉及到大量的对象,影响了性能

 

 

OpenLayers项目分析——(九)控件

(九) OpenLayers中的控件

 

   OpenLayers中的控件,是通过加载到地图上而起作用的,也算地图表现的一部分。同时,控件需要对地图发生作用,所以每个控件也持有对地图( map对象)的引用。

 

  前面说过,控件是于事件相关联的。具体的说就是控件的实现是依赖于事件绑定的,每个 OpenLayers.Control及其子类的实例都会持有一个 handler的引用的。

 

  那么,怎么来创建并添加一个控件呢?用下面的语句:

 

   //实例化一个控件

   var control1 = new OpenLayers.Control({div: myDiv});

 

   //向地图中添加控件

   var map = new OpenLayers.Map('map', { controls: [] });

   map.addControl(control1 );

 

对一些常用的 OpenLayers控件,项目本身都封装好了,用下面的语句添加:

 

   map.addControl(new OpenLayers.Control.PanZoomBar());

 

   map.addControl(new OpenLayers.Control.MouseToolbar());

 

   map.addControl(new OpenLayers.Control.LayerSwitcher({'ascending':false}));

 

   map.addControl(new OpenLayers.Control.Permalink());

 

   map.addControl(new OpenLayers.Control.Permalink('permalink'));

 

   map.addControl(new OpenLayers.Control.MousePosition());

 

   map.addControl(new OpenLayers.Control.OverviewMap());

 

    map.addControl(new OpenLayers.Control.KeyboardDefaults());

 

 

  先看看 OpenLayers. Control 基类的实现过程,再选择几个典型的子类分析一下。

 

   OpenLayers. Control

 

   //设置控件的 map属性,即控件所引用的地图

    setMap: function(map) {

        this.map = map;

        if (this.handler) {

            this.handler.setMap(map);

        }

    }

 

   //drew方法,当控件准备显示在地图上是被调用。当然,这个方法只对有图标的控件起 

   //作用。

    draw: function (px) {

        if (this.div == null) {

            this.div = OpenLayers.Util.createDiv();

            this.div.id = this.id;

            this.div.className = this.displayClass;

        }

        if (px != null) {

            this.position = px.clone();

        }

        this.moveTo(this.position);       

        return this.div;

    }

 

  前面说过, OpenLayers.Control及其子类的实例都是会持有一个 handler的引用的,因为每个控件起作用时,鼠标事件都是不一样的,这需要动态的绑定和接触绑定。在 OpenLayers.Control中是通过 active deactive两个方法实现,就是动态的激活和注销。

 

   //激活方法

    activate: function () {

        if (this.active) {

            return false;

        }

        if (this.handler) {

            this.handler.activate();

        }

        this.active = true;

        return true;

    }

 

   //注销方法

    deactivate: function () {

        if (this.active) {

            if (this.handler) {

                this.handler.deactivate();

            }

            this.active = false;

            return true;

        }

        return false;

    }

 

  再来看 OpenLayers.Control的子类,即各类“特色”控件。选鹰眼控件 OpenLayers. Control. OverviewMap 和矢量编辑工具条控件 OpenLayers. Control. EditingToolbar来说。

 

  顺便说一句, OpenLayers中的控件有些是需要图标的,像 EditingToolbar,有些是不需要的,像 OpenLayers. Control. DragPan

 

   OpenLayers. Control. OverviewMap

  “鹰眼”实际上也是地图导航的一种形式,在外部形态上跟图层开关控件有点儿像。

添加鹰眼控件的语句:

   map.addControl(new OpenLayers.Control.OverviewMap());

  在它实现的成员函数中, draw函数是核心,继承基类 OpenLayers.Control,在地图中显示这个控件。

 

  此控件关联了一些浏览器事件,比如

    rectMouseDown: function (evt) {

        if(!OpenLayers.Event.isLeftClick(evt)) return;

        this.rectDragStart = evt.xy.clone();

        this.performedRectDrag = false;

        OpenLayers.Event.stop(evt);

    }

 

   OpenLayers. Control. EditingToolbar

 

   OpenLayers 2.3版就对矢量编辑进行了支持,就是图上右上角几个图标。完成点、线、面的编辑功能。

 

  同样,它也是用 drew方法激活:

 

    draw: function() {

        Var   div  = OpenLayers.Control.Panel.prototype.draw.apply(this, arguments);

        this.activateControl(this.controls[0]);

        return div;

    }

 

  下面的代码是使用此控件的具体过程:

   Var map, layer;   

     map = new OpenLayers.Map( 'map', { controls: [] } );

     layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",

             "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'} );

     map.addLayer(layer);

     vlayer = new OpenLayers.Layer.Vector( "Editable" );

     map.addLayer(vlayer);

     map.addControl(new OpenLayers.Control.PanZoomBar());

     map.addControl(new OpenLayers.Control.EditingToolbar(vlayer));

 map.setCenter(new OpenLayers.LonLat(lon, lat), zoom);

 

OpenLayers项目分析——(十)事件机制分析

(十) OpenLayers事件机制分析

 

   OpenLayers中的事件封装是其一大亮点,非常值得学习。说到事件机制,在宏观上不得不涉及控件 OpenLayers.Control类、 OpenLayers. Marker类、 OpenLayers.Icon类等。是这样,在外观上控件通过 Marker Icon表现出来,而事件包含在控件之后,用他们自己的话说就是: The controls that wrap handlers define the methods that correspond to these abstract events 。顺便再说一句,控件实现的核心是 handler类,每个控件中都包含对 handler的引用,通过 active deactive两个方法,实现动态的激活和注销。

 

   OpenLayers中的事件有两种:一种是浏览器事件(比如 onclick onmouseup等),另一种是自定义的事件。自定义的事件像 addLayer ,addControl等,不象浏览器事件会绑定相应的 dom节点,它是与 layer map等关联的。

 

   OpenLayers中支持的浏览器事件类型有(以常量的形式提供的): 

 

    BROWSER_EVENTS: [

        "mouseover", "mouseout",

        "mousedown", "mouseup", "mousemove",

        "click", "dblclick",

        "resize", "focus", "blur" ]  

 

  看看构造函数的的实现过程:

    initialize: function (object, element, eventTypes, fallThrough) {

        this.object     = object;

        this.element    = element;

        this.eventTypes = eventTypes;

        this.fallThrough = fallThrough;

        this.listeners = {};

 

        // keep a bound copy of handleBrowserEvent() so that we can

        // pass the same function to both Event.observe() and .stopObserving()

        this.eventHandler = OpenLayers.Function.bindAsEventListener(

            this.handleBrowserEvent, this

        );

 

        // if eventTypes is specified, create a listeners list for each

        // custom application event.

        if (this.eventTypes != null) {

            for (var i = 0; i < this.eventTypes.length; i++) {

                this.addEventType(this.eventTypes[i]);

            }

        }

 

        // if a dom element is specified, add a listeners list

        // for browser events on the element and register them

        if (this.element != null) {

            this.attachToElement(element);

        }

    }

 

  可以这样理解:

   initialize object, element, eventTypes, fallThrough )方法会将以数组 eventTypes的每个元素为 key建立哈希表 listeners,表中每个键对应一个数组。还会给 this.eventHandler赋值,它实际只是一个包装了 triggerEvent事件触发函数的方法,所有的事件,包括浏览器事件和自定义事件都是通过它来中转的。然后 initialize将所有的浏览器事件放入 listeners中,并为其绑定相应的 dom节点 element this.eventHandler事件处理函数 OpenLayers.Event.observe(element, eventType, this.eventHandler) ,节点上事件触发的时候会把事件传给 this.eventHandler,它调用 triggerEvent,从而将事件传出来。

 

  来看其他的成员函数:

   addEventType Add a new event type to this events object

   attachToElement:把浏览器事件关联到相应的 DOM元素上;

   register Register an event on the events object.

        register: function (type, obj, func) {

           if (func != null) {

               if (obj == null) {

                  obj = this.object;

              }

            var listeners = this.listeners[type];

            if (listeners != null) {

                listeners.push( {obj: obj, func: func} );

            }

        }

    }

 

其中, func参数是预先定义的回调函数。

 

   unregister:注销方法;

   remove Remove all listeners for a given event type.

   triggerEvent Trigger a specified registered event

 

OpenLayers Vector Markers

OpenLayers 2.4版本中历史性地添加了 Vector图层的支持。这个功能分别在不同的浏览器上用 SVG/VML实现,其难度可以想象。 Vector的出现可能大大增加开源 WebGIS客户端的功能。

 

不过问题也随之而来,在使用 Vector 的时候,我们通常还要添加一个 SelectFeature 控件。这个控件的功能是使矢量的 Feature 可选,或是响应其他鼠标事件。问题就在于添加了 SelectFeature 之后,原本的 Marker 就不能再捕捉到事件,导致 Popup 之类的功能失效(包括 Popup 本身也不能捕捉到事件)。

 

鱼和熊掌不能兼得,不过 OpenLayers 2.4 中已经给 Vector图层里增加了 createMarker createPopup 两个方法 ,它的注释是“ HACK - we need to decide if all vector features should be able to create markers ”。料想利用这两个方法构造的 marker和应该是可以解决前面的问题。

 

Vector Marker的冲突可能还是会继续一段时间,看起来确实是一个小小的缺陷。

 

下一个

 

OpenLayers是一个开源的 js框架,用于在您的浏览器中实现地图浏览的效果和基本的 zoom pan等功能。 OpenLayers支持的地图来源包括了 WMS GoogleMap KaMap MSVirtualEarth等等,您也可以用简单的图片作为源,在这一方面 OPenLayers提供了非常多的选择。

 

要使用 OpenLayers,您可以到它的官方网站 http://www.openlayers.org下载他的压缩包,解压后可以看到其中的一些目录和文件。拷贝 dist目录下的 OpenLayer.js、根目录下的 lib目录、根目录下的 img目录到你网站的 scripts目录下(当然,这个只是例子,您网站的目录结构您自己说得算,只要保证 OpenLayers.js /lib /img在同一目录中即可)。

 

接下来创建一个 index.html作为查看地图的页面。导入 OpenLayers.js和你将要创建的 js。内容需要一个 div,我们给它的 id起名叫做 area。你有必要在写一些 CSS限定 #area的宽度和高度,如果乐意,加上一个 border也是很不错的选择。

 

废话不多说,我们首先要创建一个 OpenLayer.Map对象的实例 :

var map = new OpenLayers.Map("area");

其中的参数可以传 id,也可以传 ElementObject,当然 id更加方便一些。

 

接下来就是向地图中添加图层,通常情况下使用 OpenLayers.Layer的子类来完成图层的初始化。

OpenLayers提供了一下 Layers的扩展:

OpenLayers.Layer.Image

OpenLayers.Layer.HTTPRequest

OpenLayers.Layer.Grid

OpenLayers.Layer.WMS

OpenLayers.Layer.KaMap

OpenLayers.Layer.EventPane

OpenLayers.Layer.Google

OpenLayers.Layer.VirtualEarth

OpenLayers.Layer.Markers

OpenLayers.Layer.Text

OpenLayers.Layer.GeoRSS

OpenLayers.Layer.Boxes

OpenLayers.Layer.TMS

Image类封装一个实际图象作为图曾内容

HTTPRequest类可以接收一个动态生成的图片,你可以通过 HTTPRequest类的参数向服务器发送参数

Grid类是 HTTPRequest类的子类,提供更加详细的方法

WMS类用于连接 WMS服务器以获得图象

KaMap类用于连接 MapServer

EventPane类作为用于接收用户操作的图层

Google类用于从 Google获得图象,它仍然需要你从 Google获得 API KEY,并且 include

VirtualEarth类用于操作 VirtualEarth的图层

Markers类用于生成接收和显示用户本地标记的图层

Text类用于接收 CSV文件

GeoRSS类是 Marker类的子类,用于封装接收 GeoRSS并在图层中作出 marker

Boxes同样也是 Marker类的子类,可以用 div来做 marker,而非 image

TMS用于接收 TMS服务器的地图

 

创建完图层后,可以用 Map addLayer(layer)方法插入,并执行 Map zoomToMaxExtent()方法让地图合适地显示。

 

OpenLayers还提供了丰富的 Control类为地图浏览添加一些工具,继承自 OpenLayers.Control

OpenLayers.Control.LayerSwitcher

OpenLayers.Control.MouseDefaults

OpenLayers.Control.MousePosition

OpenLayers.Control.MouseToolbar

OpenLayers.Control.OverviewMap

OpenLayers.Control.PanZoom

OpenLayers.Control.PanZoomBar

OpenLayers.Control.Permalink

OpenLayers.Control.Scale

这些类的实例会在地图浏览的“窗口”上增加一些工具栏或是“按钮”,增加互动性和功能性。

 

OpenLayers对常用的数据结构进行了封装

OpenLayers.LonLat

OpenLayers.Size

OpenLayers.Pixel

OpenLayers.Bounds

以便于操作。

 

此外 OpenLayers.Util类可以对图片载入错误时图片框的颜色和图片框中默认的图片进行自定义,这一点是非常方便的。 OpenLayers Ajax类对创建 XHR对象的过程进行了封装,可以使用它进行简单的 Ajax操作。

分享到:
评论
3 楼 chen4w 2012-04-08  
good!
2 楼 wangtf211 2011-11-03  
这么好的东西怎么没人看??一下
1 楼 javalinjx 2011-09-14  
真不错,之前也了解过geoserver,学习。。

相关推荐

Global site tag (gtag.js) - Google Analytics