OpenLayers源码学习16:图层Layer_1

从图层开始才是真正的地图展示, 看了一半最迷糊的是scale, resolutions, bounds的换算,
这回先把之前的通用函数扫清, 下次分析具体换算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
OpenLayers.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,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
//构造,
//传参: 图层名, 构造配置项
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
},
//优先是 imageSize
getImageSize: 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;
},
// 设置是否是baselayer
setIsBaseLayer: function(isBaseLayer) {
if (isBaseLayer != this.isBaseLayer) {//异或当前状态
this.isBaseLayer = isBaseLayer;//设置状态位
if (this.map != null) {
this.map.events.triggerEvent("changebaselayer", {
layer: this
});
}
}
},