OpenLayers源码学习18:图层Layer.Grid_1

再往后一个子类就是Layer.Grid, 这个不知道会不会用上tile瓦片类…

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
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
OpenLayers.Layer.Grid = OpenLayers.Class(OpenLayers.Layer.HTTPRequest, {
// <OpenLayers.Size>
tileSize: null,
// 瓦片最开始的角落: 继承于layer's <maxExtent>. 默认是左下角
//"tl" (top left), "tr" (top right), "bl" (bottom left), and "br" (bottom right)
tileOriginCorner: "bl",
// <OpenLayers.LonLat>如果提供, 就按这个坐标对齐瓦片
tileOrigin: null,
// 瓦片设置
tileOptions: null,
//指定使用瓦片的类型
tileClass: OpenLayers.Tile.Image,
//二维数组 表示行列 存储瓦片, Array(Array(<OpenLayers.Tile>)).
grid: null,
// 是否设置图层到single-tile模式(不知道干嘛的...)
singleTile: false,
// 仅用在single-tile模式, 瓦片/map的比率
ratio: 1.5,
//仅用在 gridded mode, 拖动时瓦片缓存
buffer: 0,
// 变换效果( "resize" "map-resize" null)
transitionEffect: "resize",
//加载瓦片数量
numLoadingTiles: 0,
// 服务器分辨率
serverResolutions: null,
//正在加载标志
loading: false,
// {DOMElement}背景缓存
backBuffer: null,
// 每次grid重新初始化更新
gridResolution: null,
// back buffer is created新建时设置
backBufferResolution: null,
// 左上角坐标缓存
backBufferLonLat: null,
// 背景缓存的计时器
backBufferTimerId: null,
// 删除动画延迟
removeBackBufferDelay: null,
//瓦片类名 , 在style.css
className: null,
/**
* 事件
* layer.events.register(type, obj, listener);
* 支持事件类型:
* addtile ,tileloadstart ,tileloaded ,tileerror ,retile
*/
// 对象包含以下属性: tilelon, tilelat, startcol,startrow
gridLayout: null,
// 1是从顶部开始, -1是从底部开始
rowSign: null,
//变换事件
transitionendEvents: [
'transitionend', 'webkitTransitionEnd', 'otransitionend',
'oTransitionEnd'
],
//构造
initialize: function(name, url, params, options) {
//先使用父类构造
OpenLayers.Layer.HTTPRequest.prototype.initialize.apply(this,
arguments);
//处理本类属性
this.grid = [];
this._removeBackBuffer = OpenLayers.Function.bind(this.removeBackBuffer, this);
this.initProperties();
this.rowSign = this.tileOriginCorner.substr(0, 1) === "t" ? 1 : -1;
},
// 初始化
initProperties: function() {
//单瓦片模式就没有清除buffer延迟, 否则就2500
if (this.options.removeBackBufferDelay === undefined) {
this.removeBackBufferDelay = this.singleTile ? 0 : 2500;
}
//css类名
if (this.options.className === undefined) {
this.className = this.singleTile ? 'olLayerGridSingleTile' :
'olLayerGrid';
}
},
//把map对象的引用写在父类里, 更新样式
setMap: function(map) {
OpenLayers.Layer.HTTPRequest.prototype.setMap.call(this, map);
OpenLayers.Element.addClass(this.div, this.className);
},
//
removeMap: function(map) {
this.removeBackBuffer();
},
//销毁, 先销毁本类, 再销毁父类
destroy: function() {
this.removeBackBuffer();
this.clearGrid();
this.grid = null;
this.tileSize = null;
OpenLayers.Layer.HTTPRequest.prototype.destroy.apply(this, arguments);
},
/**
* APIMethod: mergeNewParams
* 这个方法在父类里, 这会继承来
*/
// 删除网格,
clearGrid:function() {
if (this.grid) {
for(var iRow=0, len=this.grid.length; iRow<len; iRow++) {
var row = this.grid[iRow];
for(var iCol=0, clen=row.length; iCol<clen; iCol++) {
var tile = row[iCol];
this.destroyTile(tile);//删除二维数组的各个title
}
}
this.grid = [];//各种置空
this.gridResolution = null;
this.gridLayout = null;
}
},
//添加配置项
addOptions: function (newOptions, reinitialize) {
var singleTileChanged = newOptions.singleTile !== undefined &&
newOptions.singleTile !== this.singleTile;
//父类的addOptions
OpenLayers.Layer.HTTPRequest.prototype.addOptions.apply(this, arguments);
//几乎是重新初始化
if (this.map && singleTileChanged) {
this.initProperties();
this.clearGrid();
this.tileSize = this.options.tileSize;
this.setTileSize();
//init完 移动一次
this.moveTo(null, true);
}
},
//克隆
clone: function (obj) {
if (obj == null) {
obj = new OpenLayers.Layer.Grid(this.name,
this.url,
this.params,
this.getOptions());
}
//扩展父类
obj = OpenLayers.Layer.HTTPRequest.prototype.clone.apply(this, [obj]);
// 瓦片的克隆
if (this.tileSize != null) {
obj.tileSize = this.tileSize.clone();
}
// 这些东西不拷贝, 而是用新的 空的
obj.grid = [];
obj.gridResolution = null;
obj.backBuffer = null;
obj.backBufferTimerId = null;
obj.loading = false;
obj.numLoadingTiles = 0;
return obj;
},
// 地图移动时触发. 用于调整bounds
// 参数 bounds - {<OpenLayers.Bounds>}, zoomChanged - {Boolean}, dragging - {Boolean}
moveTo:function(bounds, zoomChanged, dragging) {
//父级moveTo
OpenLayers.Layer.HTTPRequest.prototype.moveTo.apply(this, arguments);
//不传bounds, 就按map的当前extent
bounds = bounds || this.map.getExtent();
if (bounds != null) {
// 有grid或zoom改变了, 就必须forceReTile
var forceReTile = !this.grid.length || zoomChanged;
// 瓦片Bounds
var tilesBounds = this.getTilesBounds();
// 当前 map 分辨率
var resolution = this.map.getResolution();
// 服务端支持的map resolution
var serverResolution = this.getServerResolution(resolution);
if (this.singleTile) {
// 单瓦片模式
if ( forceReTile || (!dragging && !tilesBounds.containsBounds(bounds))) {
if(zoomChanged && this.transitionEffect !== 'resize') {
this.removeBackBuffer();
}
if(!zoomChanged || this.transitionEffect === 'resize') {
this.applyBackBuffer(resolution);
}
this.initSingleTile(bounds);
}
} else {
// 为了减少循环次数, 有时需要 forceReTile
forceReTile = forceReTile ||
!tilesBounds.intersectsBounds(bounds, {
worldBounds: this.map.baseLayer.wrapDateLine &&
this.map.getMaxExtent()
});
if(forceReTile) {
if(zoomChanged && (this.transitionEffect === 'resize' ||
this.gridResolution === resolution)) {
this.applyBackBuffer(resolution);
}
this.initGriddedTiles(bounds);
} else {
//正常move
this.moveGriddedTiles();
}
}
}
},
// 获得瓦片
// 传入一个瓦片在地图上的位置{<OpenLayers.LonLat>}, 计算出瓦片和像素偏移量. 没有返回null
//返回结果的数据结构: tile ({<OpenLayers.Tile>}),i ({Number} x-pixel offset from top left), and j ({Integer} y-pixel offset from top left).
getTileData: function(loc) {
var data = null,
x = loc.lon,//传入的经纬度
y = loc.lat,
numRows = this.grid.length;//行数
if (this.map && numRows) {
var res = this.map.getResolution(),//分辨率
tileWidth = this.tileSize.w,
tileHeight = this.tileSize.h,//瓦片长宽
bounds = this.grid[0][0].bounds,//第一张瓦片的bounds
left = bounds.left,//第一张瓦片的最左
top = bounds.top;//第一张瓦片的最顶
if (x < left) {
// 处理视野内多个世界world地图
if (this.map.baseLayer.wrapDateLine) {
var worldWidth = this.map.getMaxExtent().getWidth();//最大extent的宽度
var worldsAway = Math.ceil((left - x) / worldWidth);//距离world的比率
x += worldWidth * worldsAway;//乘一下 计算横向距离
}
}
// 瓦片距离给定坐标的偏移个数
// (给定坐标的经纬度 - 第一张瓦片的最左经纬度) / (分辨率 x 瓦片宽度)
var dtx = (x - left) / (res * tileWidth);
var dty = (top - y) / (res * tileHeight);
// 二维数组的行列号
var col = Math.floor(dtx);
var row = Math.floor(dty);
if (row >= 0 && row < numRows) {
var tile = this.grid[row][col];//放入二维数组进行缓存
if (tile) {
data = {
tile: tile,
//计算瓦片的像素偏移
i: Math.floor((dtx - col) * tileWidth),
j: Math.floor((dty - row) * tileHeight)
};
}
}
}
return data;
},
//销毁瓦片
destroyTile: function(tile) {
this.removeTileMonitoringHooks(tile);
tile.destroy();
},
// 返回最接近的 服务端支持的分辨率
getServerResolution: function(resolution) {
var distance = Number.POSITIVE_INFINITY;//近似值
resolution = resolution || this.map.getResolution();//分辨率
if(this.serverResolutions &&
OpenLayers.Util.indexOf(this.serverResolutions, resolution) === -1) {
var i, newDistance, newResolution, serverResolution;
for(i=this.serverResolutions.length-1; i>= 0; i--) {
newResolution = this.serverResolutions[i];
newDistance = Math.abs(newResolution - resolution);//冒泡去找近似值最小的值
if (newDistance > distance) {
break;
}
distance = newDistance;
serverResolution = newResolution;
}
resolution = serverResolution;
}
return resolution;
},
//取到服务器支持的最合适的zoom值
getServerZoom: function() {
var resolution = this.getServerResolution();
return this.serverResolutions ?
OpenLayers.Util.indexOf(this.serverResolutions, resolution) ://如果有列表 去数组里查
this.map.getZoomForResolution(resolution) + (this.zoomOffset || 0);//没有列表, 从分辨率算, 再加zoom偏移
},