Layer类介绍
# 概述
本文将介绍Layer
类,该类是所有图层类型都会继承的基类,一般情况下,在添加自定义图层,并使用自定义的render
函数时,该类才应该被实例化。
# 源码剖析
Layer
类继承于BaseLayer
类,在前面提过BaseLayer
类主要是设置对象的一些属性值,以及提供GET
和SET
两类方法。Layer
类的实现如下:
class Layer extends BaseLayer {
constructor(options) {
const baseOptions = Object.assign({}, options);
delete baseOptions.source;
super(baseOptions);
this.on;
this.once;
this.un;
this.mapPrecomposeKey_ = null;
this.mapRenderKey_ = null;
this.sourceChangeKey_ = null;
this.renderer_ = null;
this.sourceReady_ = false;
this.rendered = false;
if (options.render) {
this.render = options.render;
}
if (options.map) {
this.setMap(options.map);
}
this.addChangeListener(
LayerProperty.SOURCE,
this.handleSourcePropertyChange_
);
const source = options.source ? options.source : null;
this.setSource(source);
}
getLayersArray(array) {
array = array ? array : [];
array.push(this);
return array;
}
getLayerStatesArray(states) {
states = states ? states : [];
states.push(this.getLayerState());
return states;
}
getSource() {
return this.get(LayerProperty.SOURCE) || null;
}
getRenderSource() {
return this.getSource();
}
getSourceState() {
const source = this.getSource();
return !source ? "undefined" : source.getState();
}
handleSourceChange_() {
this.changed();
if (this.sourceReady_ || this.getSource().getState() !== "ready") {
return;
}
this.sourceReady_ = true;
this.dispatchEvent("sourceready");
}
handleSourcePropertyChange_() {
if (this.sourceChangeKey_) {
unlistenByKey(this.sourceChangeKey_);
this.sourceChangeKey_ = null;
}
this.sourceReady_ = false;
const source = this.getSource();
if (source) {
this.sourceChangeKey_ = listen(
source,
EventType.CHANGE,
this.handleSourceChange_,
this
);
if (source.getState() === "ready") {
this.sourceReady_ = true;
setTimeout(() => {
this.dispatchEvent("sourceready");
}, 0);
}
}
this.changed();
}
getFeatures(pixel) {
if (!this.renderer_) {
return Promise.resolve([]);
}
return this.renderer_.getFeatures(pixel);
}
getData(pixel) {
if (!this.renderer_ || !this.rendered) {
return null;
}
return this.renderer_.getData(pixel);
}
isVisible(view) {
let frameState;
const map = this.getMapInternal();
if (!view && map) {
view = map.getView();
}
if (view instanceof View) {
frameState = {
viewState: view.getState(),
extent: view.calculateExtent(),
};
} else {
frameState = view;
}
if (!frameState.layerStatesArray && map) {
frameState.layerStatesArray = map.getLayerGroup().getLayerStatesArray();
}
let layerState;
if (frameState.layerStatesArray) {
layerState = frameState.layerStatesArray.find(
(layerState) => layerState.layer === this
);
} else {
layerState = this.getLayerState();
}
const layerExtent = this.getExtent();
return (
inView(layerState, frameState.viewState) &&
(!layerExtent || intersects(layerExtent, frameState.extent))
);
}
getAttributions(view) {
if (!this.isVisible(view)) {
return [];
}
const getAttributions = this.getSource()?.getAttributions();
if (!getAttributions) {
return [];
}
const frameState =
view instanceof View ? view.getViewStateAndExtent() : view;
let attributions = getAttributions(frameState);
if (!Array.isArray(attributions)) {
attributions = [attributions];
}
return attributions;
}
render(frameState, target) {
const layerRenderer = this.getRenderer();
if (layerRenderer.prepareFrame(frameState)) {
this.rendered = true;
return layerRenderer.renderFrame(frameState, target);
}
return null;
}
unrender() {
this.rendered = false;
}
getDeclutter() {
return undefined;
}
renderDeclutter(frameState, layerState) {}
renderDeferred(frameState) {
const layerRenderer = this.getRenderer();
if (!layerRenderer) {
return;
}
layerRenderer.renderDeferred(frameState);
}
setMapInternal(map) {
if (!map) {
this.unrender();
}
this.set(LayerProperty.MAP, map);
}
getMapInternal() {
return this.get(LayerProperty.MAP);
}
setMap(map) {
if (this.mapPrecomposeKey_) {
unlistenByKey(this.mapPrecomposeKey_);
this.mapPrecomposeKey_ = null;
}
if (!map) {
this.changed();
}
if (this.mapRenderKey_) {
unlistenByKey(this.mapRenderKey_);
this.mapRenderKey_ = null;
}
if (map) {
this.mapPrecomposeKey_ = listen(
map,
RenderEventType.PRECOMPOSE,
this.handlePrecompose_,
this
);
this.mapRenderKey_ = listen(this, EventType.CHANGE, map.render, map);
this.changed();
}
}
handlePrecompose_(renderEvent) {
const layerStatesArray = renderEvent.frameState.layerStatesArray;
const layerState = this.getLayerState(false);
assert(
!layerStatesArray.some(
(arrayLayerState) => arrayLayerState.layer === layerState.layer
),
"A layer can only be added to the map once. Use either `layer.setMap()` or `map.addLayer()`, not both."
);
layerStatesArray.push(layerState);
}
setSource(source) {
this.set(LayerProperty.SOURCE, source);
}
getRenderer() {
if (!this.renderer_) {
this.renderer_ = this.createRenderer();
}
return this.renderer_;
}
hasRenderer() {
return !!this.renderer_;
}
createRenderer() {
return null;
}
disposeInternal() {
if (this.renderer_) {
this.renderer_.dispose();
delete this.renderer_;
}
this.setSource(null);
super.disposeInternal();
}
}
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
# Layer
类的构造函数
Layer
类构造函数接受一个参数Options
对象将其赋值给变量baseOptions
,并删除baseOptions
的source
属性,通过super(baseOptions)
初始化父类;然后初始化了几个变量;
然后判断options.render
是否存在,若存在则赋值给this.render
,覆盖Layer
类中的render
方法;判断options.map
是否存在,若存在,则调用this.setMap
方法,如下:
render
方法
render(frameState, target) {
const layerRenderer = this.getRenderer();
if (layerRenderer.prepareFrame(frameState)) {
this.rendered = true;
return layerRenderer.renderFrame(frameState, target);
}
return null;
}
2
3
4
5
6
7
8
9
render
方法的作用就是负责渲染图层,每种类型的图层都有之与其对应的图层渲染器。它接受两个参数帧状态frameState
和目标容器target
。render
方法内部就是获取调用getRenderer
获取图层渲染器,然后判断layerRenderer.prepareFrame(frameState)
是否准备渲染帧,若返回true
,则修改this.rendered
值为true
,调用layerRenderer.renderFrame(frameState, target)
将帧渲染到target
即网页容器中;若返回false
,则render
方法返回null
setMap
方法
setMap(map) {
if (this.mapPrecomposeKey_) {
unlistenByKey(this.mapPrecomposeKey_);
this.mapPrecomposeKey_ = null;
}
if (!map) {
this.changed();
}
if (this.mapRenderKey_) {
unlistenByKey(this.mapRenderKey_);
this.mapRenderKey_ = null;
}
if (map) {
this.mapPrecomposeKey_ = listen(
map,
RenderEventType.PRECOMPOSE,
this.handlePrecompose_,
this,
);
this.mapRenderKey_ = listen(this, EventType.CHANGE, map.render, map);
this.changed();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
setMap
方法在Layer
类中调用时,参数map
肯定存在,因此现阶段只讨论map
存在的情况;map
存在时,会调用listen
方法注册postcompose
类型的this.handlePrecompose_
事件和change
类型的map.render
事件,最后调用this.changed
方法。
listen
方法,listen
方法在中提过,本质上还是调用EventTarget
类中的addEventListener
方法,而最后调用的this.changed
方法会调用Observable
类中的changed
方法,继而调用dispatchEvent
派发change
类型的注册事件,前面注册的map.render
事件,即参数map
的render
方法。
最后调用this.addeventListener
方法注册source
类型的this.handleSourcePropertyChange_
事件;然后调用setSource
方法。
setSource
方法
setSource(source) {
this.set(LayerProperty.SOURCE, source);
}
2
3
setSource
方法就是调用BaseObject
类中的set
方法,第一次调用时(新旧值不一样时)会触发source
的注册事件,即handleSourcePropertyChange_
方法
handleSourcePropertyChange_
handleSourcePropertyChange_() {
if (this.sourceChangeKey_) {
unlistenByKey(this.sourceChangeKey_);
this.sourceChangeKey_ = null;
}
this.sourceReady_ = false;
const source = this.getSource();
if (source) {
this.sourceChangeKey_ = listen(
source,
EventType.CHANGE,
this.handleSourceChange_,
this,
);
if (source.getState() === 'ready') {
this.sourceReady_ = true;
setTimeout(() => {
this.dispatchEvent('sourceready');
}, 0);
}
}
this.changed();
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
handleSourcePropertyChange_
方法首先会判断this.sourceChangeKey_
是否存在,若存在则解除EventKey
键为this.sourceChangeKey_
的监听,然后将其置为null
;然后设置this.sourceReady_
为false
。调用this.getSource()
方法,它内部就是调用BaseObject
类的get
方法获取source
的值并返回,若source
存在,则注册change
类型的handleSourceChange_
事件;
判断图层源source
的状态是否为ready
,若是,则设置this.sourceReady_
为true
,然后设置一个定时器调用dispatcheEvent('sourceready')
方法。
最后调用changed
事件,派发事件,执行类型为change
的注册事件,调用handleSourceChange_
方法。而handleSourceChange_
内部还是会在this.sourceReady_
为false
或者source
为ready
的前提下去调用dispatcheEvent('sourceready')
方法。
# Layer
类的其它函数
getLayersArray
方法:获取图层数组getLayerStatesArray
方法:获取图层状态数组getRenderSource
方法:获取渲染的图层源getSourceState
方法:获取图层源状态getFeatures
方法:接受一个参数pixel
,若this.renderer
渲染器不存在,则返回一个空数组;否则调用渲染器的getFeatures
方法getData
方法:同上,若渲染器不存在则返回null
,否则调用渲染器上的getData
方法isVisible
方法:
isVisible(view) {
let frameState;
const map = this.getMapInternal();
if (!view && map) {
view = map.getView();
}
if (view instanceof View) {
frameState = {
viewState: view.getState(),
extent: view.calculateExtent(),
};
} else {
frameState = view;
}
if (!frameState.layerStatesArray && map) {
frameState.layerStatesArray = map.getLayerGroup().getLayerStatesArray();
}
let layerState;
if (frameState.layerStatesArray) {
layerState = frameState.layerStatesArray.find(
(layerState) => layerState.layer === this,
);
} else {
layerState = this.getLayerState();
}
const layerExtent = this.getExtent();
return (
inView(layerState, frameState.viewState) &&
(!layerExtent || intersects(layerExtent, frameState.extent))
);
}
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
isVisible
方法用于判断图层在当前地图中是否可见,主要判断图层的状态和地图视图view
的帧状态,涉及到范围和分辨率以及visiable
getAttributions
方法:
getAttributions(view) {
if (!this.isVisible(view)) {
return [];
}
const getAttributions = this.getSource()?.getAttributions();
if (!getAttributions) {
return [];
}
const frameState =
view instanceof View ? view.getViewStateAndExtent() : view;
let attributions = getAttributions(frameState);
if (!Array.isArray(attributions)) {
attributions = [attributions];
}
return attributions;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
getAttributions
方法用于获取图层源的各种属性,参数是一个view
,首先判断视图的可见性,若不可见,则返回一个空数组,否则调用图层源的getAttributions()
方法,返回值保存在变量getAttributions
中,若变量getAttributions
不存在,则返回一个空数组;否则调用getAttributions(frameState)
。
setMapInternal
和getMapInternal
方法就是用于设置和获取对象的map
getRenderer
方法:获取渲染器hasRenderer
方法:判断是否存在渲染器createRender
方法:创建一个渲染器,在Layer
类中,返回一个null
,该方法应该会在Layer
的子类被重写disposeInternal
方法:Layer
类的清理方法,判断渲染器是否存在,若存在则调用渲染器的dispose
方法,然后删除渲染器;然后调用this.setSource(null)
,设置空的图层源,重置一些状态,最后调用父类的disposeInternal
方法,执行父类的清除函数。
# 总结
本文主要介绍Layer
类中重要的方法,如render
方法和setSource
的逻辑处理。