OpenLayers源码学习16:图层Layer_1 Posted on 2015-03-12 | In OpenLayers学习 | 从图层开始才是真正的地图展示, 看了一半最迷糊的是scale, resolutions, bounds的换算,这回先把之前的通用函数扫清, 下次分析具体换算 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114OpenLayers.Layer = OpenLayers.Class({ id: null, name: null, //dom元素 div: null, //透明度 opacity: 1, //是否一直判定在range之内 alwaysInRange: null, //分辨率相关的属性配置 RESOLUTION_PROPERTIES: [ 'scales', 'resolutions', 'maxScale', 'minScale', 'maxResolution', 'minResolution', 'numZoomLevels', 'maxZoomLevel' ], /** * 注册事件 * 代码示例: * layer.events.register(type, obj, listener); * * object - {Object} A reference to layer.events.object. * element - {DOMElement} A reference to layer.events.element. * * 支持事件类型: * loadstart - 图层开始加载时候触发. 当使用向量图层用fixed和BBOX策略时, 将会使用OpenLayers.Filter * loadend - 图层加载完毕是触发. 当使用向量图层用fixed和BBOX策略时, 持有一个 OpenLayers.Protocol.Response对象 * visibilitychanged - 透明/显示变化事件,如layer的switcher * move - 图层移动, 如鼠标拖动 * moveend - 图层移动结束, 包括zoom变化 * added - 添加图层 * removed - 删除图层 */ events: null, //map对象 map: null, // 是否是baseLayer isBaseLayer: false, //透明度 alpha: false, //是否把图层名显示在layer switcher里 displayInLayerSwitcher: true, // 图层是否应该显示在map上 visibility: true, //显示 <OpenLayers.Control.Attribution> attribution: null, //当前map的分辨率是不是在min/max range里, 在<OpenLayers.Map.setCenter>里设置 inRange: false, //图片大小 <OpenLayers.Size> imageSize: null, // OPTIONS //构造器的配置对象 options: null, //每一个都会注册到 <OpenLayers.Events.on>上 eventListeners: null, // 瓦片之间的间距, 默认值0无效 gutter: 0, // 投影<OpenLayers.Projection> projection: null, // 单位'degrees' (or 'dd'), 'm', 'ft', 'km', 'mi', 'inches'. units: null, // 数组, 记录map的的scales顺序 scales: null, //数组, 记录map的 resolutions数组 resolutions: null, // <OpenLayers.Bounds>|Array , 最大范围,四至 maxExtent: null, // <OpenLayers.Bounds>|Array, 最小范围 minExtent: null, // 最大分辨率默认是360 deg / 256 px (<OpenLayers.Map.tileSize>) maxResolution: null, minResolution: null, numZoomLevels: null, minScale: null, maxScale: null, // 完全超出此图层的最大边界后, 是否请求map的瓦片 displayOutsideMaxExtent: false, //仅在baselayer上用, 标记的换日线 wrapDateLine: false, // 存储在图层上的附加信息 metadata: null, 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309//构造, //传参: 图层名, 构造配置项 initialize: function(name, options) { this.metadata = {};//附加信息先置空 options = OpenLayers.Util.extend({}, options);//合并配置 //同步alwaysInRange if (this.alwaysInRange != null) { options.alwaysInRange = this.alwaysInRange; } this.addOptions(options);//保存配置 this.name = name; if (this.id == null) {//创建自增id this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_"); this.div = OpenLayers.Util.createDiv(this.id);//图层容器 this.div.style.width = "100%"; this.div.style.height = "100%"; this.div.dir = "ltr"; this.events = new OpenLayers.Events(this, this.div); if(this.eventListeners instanceof Object) {//挨个注册传入的eventListeners的每项 this.events.on(this.eventListeners); } }}, //内存回收 destroy: function(setNewBaseLayer) { if (setNewBaseLayer == null) { setNewBaseLayer = true;//默认为true } if (this.map != null) { this.map.removeLayer(this, setNewBaseLayer);//通知所处map删掉本layer } this.projection = null; this.map = null; this.name = null; this.div = null; this.options = null; if (this.events) {//event的回收 if(this.eventListeners) { this.events.un(this.eventListeners); } this.events.destroy(); } this.eventListeners = null; this.events = null;}, //克隆clone: function (obj) { if (obj == null) { obj = new OpenLayers.Layer(this.name, this.getOptions());//默认new一个新的layer出啦 } // 合并属性 OpenLayers.Util.applyDefaults(obj, this); // 除了所持有,所处的map不能一样以外, 别的都一样 obj.map = null; return obj;}, //获得 拷贝的options对象getOptions: function() { var options = {}; for(var o in this.options) { options[o] = this[o]; } return options;}, //设置图层名, 触发事件 setName: function(newName) { if (newName != this.name) { this.name = newName; if (this.map != null) { this.map.events.triggerEvent("changelayer", { layer: this, property: "name" }); } }}, //增加配置项addOptions: function (newOptions, reinitialize) { if (this.options == null) {//不知道什么情况下this.options会为null this.options = {}; } if (newOptions) {//传入newOptions项 //构造投影 if(typeof newOptions.projection == "string") { newOptions.projection = new OpenLayers.Projection(newOptions.projection); } if (newOptions.projection) { OpenLayers.Util.applyDefaults(newOptions, OpenLayers.Projection.defaults[newOptions.projection.getCode()]); } // maxExtent和minExtent允许两种形式 if (newOptions.maxExtent && !(newOptions.maxExtent instanceof OpenLayers.Bounds)) { newOptions.maxExtent = new OpenLayers.Bounds(newOptions.maxExtent); } if (newOptions.minExtent && !(newOptions.minExtent instanceof OpenLayers.Bounds)) { newOptions.minExtent = new OpenLayers.Bounds(newOptions.minExtent); } } // 更新本layer的配置项 OpenLayers.Util.extend(this.options, newOptions); // 更新本图层对象 OpenLayers.Util.extend(this, newOptions); // 获得投影的单位 if(this.projection && this.projection.getUnits()) { this.units = this.projection.getUnits(); } // 如果本layer持有map对象 if(this.map) { // 更新对应的数据 var resolution = this.map.getResolution(); var properties = this.RESOLUTION_PROPERTIES.concat( ["projection", "units", "minExtent", "maxExtent"] ); for(var o in newOptions) { if(newOptions.hasOwnProperty(o) && OpenLayers.Util.indexOf(properties, o) >= 0) { this.initResolutions(); if (reinitialize && this.map.baseLayer === this) { // 更新中心点 this.map.setCenter(this.map.getCenter(), this.map.getZoomForResolution(resolution), false, true ); // 触发baselayer更改事件 this.map.events.triggerEvent("changebaselayer", { layer: this }); } break; } } }}, //预留接口, 子类重写onMapResize: function() { //this function can be implemented by subclasses }, //图层重绘 redraw: function() { var redrawn = false;//重回结果标志位 if (this.map) { // 重新计算Range this.inRange = this.calculateInRange(); // 计算extent var extent = this.getExtent(); if (extent && this.inRange && this.visibility) { var zoomChanged = true; this.moveTo(extent, zoomChanged, false);//move到新坐标 this.events.triggerEvent("moveend", {"zoomChanged": zoomChanged});//触发一个move方法 redrawn = true; } } return redrawn;}, //边界, zoom值, 是否正在拖拽 moveTo:function(bounds, zoomChanged, dragging) { var display = this.visibility; if (!this.isBaseLayer) {//不是baselayer的话 display = display && this.inRange;//正在显示 && 在范围内 } this.display(display);}, moveByPx: function(dx, dy) {}, // 设置所持有的map对象setMap: function(map) { if (this.map == null) {//仅在持有的map为null时生效 this.map = map; this.maxExtent = this.maxExtent || this.map.maxExtent; this.minExtent = this.minExtent || this.map.minExtent; //坐标换算 this.projection = this.projection || this.map.projection; if (typeof this.projection == "string") { this.projection = new OpenLayers.Projection(this.projection); } // 单位 this.units = this.projection.getUnits() || this.units || this.map.units; this.initResolutions(); if (!this.isBaseLayer) { this.inRange = this.calculateInRange();//baselayer的话要重新计算Range var show = ((this.visibility) && (this.inRange)); this.div.style.display = show ? "" : "none"; } this.setTileSize(); }}, afterAdd: function() {}, removeMap: function(map) { //to be overridden by subclasses}, //优先是 imageSizegetImageSize: function(bounds) { return (this.imageSize || this.tileSize); }, //设置瓦片大小 setTileSize: function(size) { var tileSize = (size) ? size : ((this.tileSize) ? this.tileSize : this.map.getTileSize()); this.tileSize = tileSize; if(this.gutter) { //需要瓦片边距的话, 用瓦片宽+2倍边距 this.imageSize = new OpenLayers.Size(tileSize.w + (2*this.gutter), tileSize.h + (2*this.gutter)); }}, getVisibility: function() { return this.visibility;}, //设置是否可见 setVisibility: function(visibility) { if (visibility != this.visibility) {//和当前状态不等时候生效 this.visibility = visibility; this.display(visibility);//下边display函数是关键 this.redraw(); if (this.map != null) { //手动触发事件 this.map.events.triggerEvent("changelayer", { layer: this, property: "visibility" }); } this.events.triggerEvent("visibilitychanged"); }}, //核心函数, 其实就是控制本layer的display值"block" 或 "none"display: function(display) { if (display != (this.div.style.display != "none")) { this.div.style.display = (display && this.calculateInRange()) ? "block" : "none"; }}, //核心函数, 这个range和bounds有什么不同calculateInRange: function() { var inRange = false; if (this.alwaysInRange) {//此配置, 就是一直inRange inRange = true; } else { if (this.map) {//得有map的前提下 var resolution = this.map.getResolution();//获得当前map的Resolution inRange = ( (resolution >= this.minResolution) && (resolution <= this.maxResolution) );//判断是否在本layer的max/min之内 } } return inRange;}, // 设置是否是baselayersetIsBaseLayer: function(isBaseLayer) { if (isBaseLayer != this.isBaseLayer) {//异或当前状态 this.isBaseLayer = isBaseLayer;//设置状态位 if (this.map != null) { this.map.events.triggerEvent("changebaselayer", { layer: this }); } }},