概述
Control
基类是通过Class.extend
定义,是Leaflet中所有控件的基类,负责管理地图控件(如缩放控件、比例尺等)的创建、定位和生命周期。
在Control.js
中除了定义Control
基类,还包括关于Map
类的扩展,主要包括管理控件(控件的添加或移除)以及控件容器的初始化。
源码分析
源码实现
Control
基类和Map
类扩展的源码实现如下:
export var Control = Class.extend({
options: {
position: "topright",
},
initialize: function (options) {
Util.setOptions(this, options);
},
getPosition: function () {
return this.options.position;
},
setPosition: function (position) {
var map = this._map;
if (map) {
map.removeControl(this);
}
this.options.position = position;
if (map) {
map.addControl(this);
}
return this;
},
getContainer: function () {
return this._container;
},
addTo: function (map) {
this.remove();
this._map = map;
var container = (this._container = this.onAdd(map)),
pos = this.getPosition(),
corner = map._controlCorners[pos];
DomUtil.addClass(container, "leaflet-control");
if (pos.indexOf("bottom") !== -1) {
corner.insertBefore(container, corner.firstChild);
} else {
corner.appendChild(container);
}
this._map.on("unload", this.remove, this);
return this;
},
remove: function () {
if (!this._map) {
return this;
}
DomUtil.remove(this._container);
if (this.onRemove) {
this.onRemove(this._map);
}
this._map.off("unload", this.remove, this);
this._map = null;
return this;
},
_refocusOnMap: function (e) {
if (this._map && e && e.screenX > 0 && e.screenY > 0) {
this._map.getContainer().focus();
}
},
});
export var control = function (options) {
return new Control(options);
};
Map.include({
addControl: function (control) {
control.addTo(this);
return this;
},
removeControl: function (control) {
control.remove();
return this;
},
_initControlPos: function () {
var corners = (this._controlCorners = {}),
l = "leaflet-",
container = (this._controlContainer = DomUtil.create(
"div",
l + "control-container",
this._container
));
function createCorner(vSide, hSide) {
var className = l + vSide + " " + l + hSide;
corners[vSide + hSide] = DomUtil.create("div", className, container);
}
createCorner("top", "left");
createCorner("top", "right");
createCorner("bottom", "left");
createCorner("bottom", "right");
},
_clearControlPos: function () {
for (var i in this._controlCorners) {
DomUtil.remove(this._controlCorners[i]);
}
DomUtil.remove(this._controlContainer);
delete this._controlCorners;
delete this._controlContainer;
},
});
源码详细解析
Control
类解析
Control
类是一个抽象类,作为一个基类使用。该类的实现主要包括如下:
- 类定义与初始化
Control
类是基于Class.extend
定义,因此在构造实例化Control
类的子类时,会默认执行initialize
方法,在initialize
方法中会将参数options
设置挂载到实例对象上;
Control
类的默认位置选项是topright
,其值可能有 topleft
, topright
, bottomleft
或者 bottomright
。
- 控件位置管理
Control
类的位置管理主要通过两个函数getPosition
和setPosition
分别用于获取和设置控制的位置。
setPosition
方法的原理是接受一个位置字符串,如上面的值之一,方法内部会先移除控件,重新赋值this.options.position
,然后再将控件添加到地图上, 最后返回控件本身。
- 控件容器与生命周期
getContainer
方法用于获取控件的HTML ELement
。
Control
类的生命周期方法就是addTo
和remove
,分别用于添加和移除控件。
addTo
方法
addTo
方法接受一个Map
对象作为参数,首先会调用remove
方法移除控件,然后将控件的位置信息赋值给this.options.position
,接着获取控件的容器元素container
,并根据位置信息将其添加到地图的相应位置。最后,为地图的unload
事件添加一个监听器,当地图卸载时,会自动移除控件。
addTo
方法中会调用子类的onAdd
方法,该方法会在Control
的子类中实现,用于创建具体控件的容器元素,并返回。
remove
方法
remove
方法用于移除控件,首先会判断控件是否已经添加到地图上,如果没有则直接返回控件本身。接着,会移除控件的容器元素,并调用子类的onRemove
方法,该方法也会在Control
的子类中实现,用于移除具体控件的容器元素。最后,为地图的unload
事件移除监听器,移除控件。
- 焦点管理
Control
类还包含一个_refocusOnMap
方法,用于在地图上重新获取焦点。该方法接受一个事件对象作为参数,如果事件对象存在且屏幕坐标大于0,则会将地图的容器元素获取焦点。
Map
类扩展解析
Map
类扩展主要包括以下内容:
- 控件管理
Map
类扩展了addControl
和removeControl
方法,分别用于添加和移除控件。
addControl
方法
addControl
方法接受一个Control
子类的实例作为参数,内部就是调用控件的addTo
方法,该方法会在Control
的子类中实现,用于将控件添加到地图的相应位置。
removeControl
方法
removeControl
方法同样也接受Control
类的实例作为参数,然后调用实例的remove
方法,并返回this
。
- 控件容器初始化
Map
类扩展了_initControlPos
和_clearControlPos
方法,分别用于初始化控件容器和清除控件容器。
_initControlPos
方法
_initControlPos
方法用于初始化控件容器,首先会创建一个名为_controlCorners
的对象,用于存储控件的四个角的容器元素。然后,根据位置信息,创建四个角的容器元素,并将其添加到_controlContainer
中。最后,将_controlContainer
添加到地图的容器元素中。
_clearControlPos
方法
_clearControlPos
方法用于清除控件容器,首先会遍历_controlCorners
对象,将其中的容器元素移除。然后,将_controlContainer
移除,并删除_controlCorners
和_controlContainer
属性。
总结
Control
基类是Leaflet中所有控件的基类,负责管理地图控件的创建、定位和生命周期。
Control
类的实现主要包括控件位置管理、控件容器与生命周期、焦点管理等。Map
类扩展主要包括控件管理和控件容器初始化。