Zoom缩放控件源码分析
# 概述
放大或缩小是地图中最基本的功能,本文主要介绍分析 Openlayers 中Zoom缩放控件的源码实现。
# 源码分析
Zoom控件继承Control类,关于Control类,可以参考这篇文章Control基类介绍 (opens new window)
如果直接实例化Zoom类,页面上显示的是 Openlayers 中原生的样式,无论是控件的标签页还是样式,我们都可以通过传参进行定制。本文只讨论默认情况,不传参的情况。
源码如下:
class Zoom extends Control {
constructor(options) {
options = options ? options : {};
super({
element: document.createElement("div"),
target: options.target,
});
const className =
options.className !== undefined ? options.className : "ol-zoom";
const delta = options.delta !== undefined ? options.delta : 1;
const zoomInClassName =
options.zoomInClassName !== undefined
? options.zoomInClassName
: className + "-in";
const zoomOutClassName =
options.zoomOutClassName !== undefined
? options.zoomOutClassName
: className + "-out";
const zoomInLabel =
options.zoomInLabel !== undefined ? options.zoomInLabel : "+";
const zoomOutLabel =
options.zoomOutLabel !== undefined ? options.zoomOutLabel : "\u2013";
const zoomInTipLabel =
options.zoomInTipLabel !== undefined ? options.zoomInTipLabel : "Zoom in";
const zoomOutTipLabel =
options.zoomOutTipLabel !== undefined
? options.zoomOutTipLabel
: "Zoom out";
const inElement = document.createElement("button");
inElement.className = zoomInClassName;
inElement.setAttribute("type", "button");
inElement.title = zoomInTipLabel;
inElement.appendChild(
typeof zoomInLabel === "string"
? document.createTextNode(zoomInLabel)
: zoomInLabel
);
inElement.addEventListener(
EventType.CLICK,
this.handleClick_.bind(this, delta),
false
);
const outElement = document.createElement("button");
outElement.className = zoomOutClassName;
outElement.setAttribute("type", "button");
outElement.title = zoomOutTipLabel;
outElement.appendChild(
typeof zoomOutLabel === "string"
? document.createTextNode(zoomOutLabel)
: zoomOutLabel
);
outElement.addEventListener(
EventType.CLICK,
this.handleClick_.bind(this, -delta),
false
);
const cssClasses =
className + " " + CLASS_UNSELECTABLE + " " + CLASS_CONTROL;
const element = this.element;
element.className = cssClasses;
element.appendChild(inElement);
element.appendChild(outElement);
this.duration_ = options.duration !== undefined ? options.duration : 250;
}
handleClick_(delta, event) {
event.preventDefault();
this.zoomByDelta_(delta);
}
zoomByDelta_(delta) {}
}
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
# Zoom控件参数
Zoom类中的构造函数接受一个参数options,若它为空或者不传,则 Openlayers 将采用默认样式。options对象可以有如下属性:
className:Zoom类名,默认为ol-zoomdelta:缩放地图的变化量,默认为1zoomInClassName:放大控件的类名,默认为ol-zoom-inzoomOutClassName:缩小控件的类名,默认为ol-zoom-outzoomInLabel:放大控件图标,默认为+zoomOutLabel:缩小控件图标,默认为\u2013(即-)zoomInTipLabel:放大控件hover时的提示,默认为Zoom inzoomOutTipLabel:缩小控件hover时的提示,默认为Zoom out
# Zoom类构造函数
Zoom类的构造函数除了根据参数options定义上述变量外,还调用super({element:document.createElement('div'),target:options.target})将element和target传给父类Control,默认情况下options.target为undefined,因此这个传值就是设置了this.element=document.createElement('div');然后就是创建放大和缩小控件的DOM元素,设置属性,并将它们插入到this.element。期间还会注册放大按钮和缩小按钮的两个事件,事件名为handleClick,不同的是delta传参不同。最后设置了this.duration_,若参数options中定义了duration属性和值,则赋给this.duration_,否则默认为250,表示是250 毫秒
# Zoom类方法介绍
Zoom类中定义了两个方法handleClick_和zoomByDelta_,handleClick_就是后者的一个调用,核心方法就是zoomByDelta_。
zoomByDelta_方法
zoomByDelta方法如下
zoomByDelta_(delta) {
const map = this.getMap();
const view = map.getView();
if (!view) {
return;
}
const currentZoom = view.getZoom();
if (currentZoom !== undefined) {
const newZoom = view.getConstrainedZoom(currentZoom + delta); //返回被限制的级别,不超出范围
if (this.duration_ > 0) {
if (view.getAnimating()) { // 若有动画正在进行,则取消动画
view.cancelAnimations();
}
view.animate({
zoom: newZoom,
duration: this.duration_,
easing: easeOut,
});
} else {
view.setZoom(newZoom);
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
在上面代码中this.getMap()实际上就是调用父类Control的getMap方法中,在Map类中实例化时,会遍历this.controls,调用setMap方法;或者在const map=new Map(...)后,用map.addControl添加控件时,会触发this.controls.addEventListener(CollectionEventType.ADD,(event) => {event.element.setMap(this);},);同样地会设置setMap,因此Zoom缩放控件被点击时触发zoomByDelta_,调用this.getMap是可以取到map对象,然后通过map.getView获取当前视图view,继而获取当前地图的级别currentZoom,进行边界判断,然后放大调用view.animate,缩小调用view.setZoom
# 总结
本文主要介绍了Openlayers中Zoom缩放控件的源码实现,讲解了缩放的核心知识。