地图表现 控件
来源:互联网 发布:自我评价 知乎 编辑:程序博客网 时间:2024/06/10 05:37
一开始看到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.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中的控件,是通过加载到地图上而起作用的,也算地图表现的一部分。同时,控件需要对地图发生作用,所以每个控件也持有对地图(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项目分析[转](七):地图表现
- OpenLayers项目分析[转](八):地图表现(续)
- OpenLayers项目分析——(七)地图表现
- OpenLayers项目分析——(八)地图表现
- 地图控件退出崩溃
- 地图符号编辑器控件
- Virtual Earth 地图控件
- 地图绘制控件
- GoogleMap地图控件应用
- 找不到地图控件了
- gMapEx地图控件
- wp7 地图控件
- 关键词叠加
- 【读书笔记】usOS-II学习笔记(2008-10-31)
- 博客群发会被K掉吗?
- 隐藏文本和链接
- 搜索引擎对SEO作弊的判定条件
- 地图表现 控件
- 别了,Windows!别了,微软!
- 哈佛经典营销案例 猪的投资与营销
- 修炼一名程序员的职业水准
- 数据结构实验1(最近就写这玩意了)
- 数据结构实验2(最近就写这玩意了)
- 数据结构实验3(最近就写这玩意了)
- 数据结构实验4
- 一个很有用的字符串分割函数