OpenLayers-------地图表现

来源:互联网 发布:亚克力 吸塑 知乎 编辑:程序博客网 时间:2024/03/29 13:37

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

 

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

 

  Map类有两个常量:Z_INDEX_BASEEVENT_TYPES,不说了,可顾名而思其意。再看它定义的一些属性:divThe element that contains the map)、baseLayerThe currently selected base layer)、eventsAn events object that handles all events on the map)。是这样,web页的div通过以idname的形式获得map对象,然后layerscontrol在加载到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 FunctionsControl FunctionsPopup FunctionsContainer Div FunctionsZoom, Center, Pan FunctionsLayer OptionsBaselayer FunctionsZooming FunctionsTranslation Functions。其中,最关键的是Layer FunctionsControl 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);

    }

 


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

 

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

 

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

 

  定义的mapevent属性,是图层对象对mapevent对象的引用;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函数,相当于析构函数;

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

 

  //移动函数

  moveTo:function(bounds, zoomChanged, dragging) {

        var display = this.visibility;

        if (!this.isBaseLayer) {

            display = display && this.inRange;

        }

        this.display(display);

    }

 

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

 

比如,initResolutionsgetResolutiongetExtent等。

 

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

 

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


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