Jinuss's blog Jinuss's blog
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript高级程序设计》
    • 《Vue》
    • 《React》
    • 《Git》
    • JS设计模式总结
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

东流

前端可视化
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript高级程序设计》
    • 《Vue》
    • 《React》
    • 《Git》
    • JS设计模式总结
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 框架

  • core模块

  • dom模块

  • control

    • Control
      • 概述
      • 源码分析
        • 源码实现
        • 源码详细解析
        • Control类解析
        • Map类扩展解析
      • 总结
    • Control.Scale
    • Control.Zoom
    • Control.Attribution
    • Control.Layers
  • geometry

  • geo

  • layer

  • Map

  • 《Leaflet源码》笔记
  • control
东流
2025-03-24
目录

Control

# 概述

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;
  },
});
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

# 源码详细解析

# Control类解析

Control类是一个抽象类,作为一个基类使用。该类的实现主要包括如下:

  1. 类定义与初始化

Control类是基于Class.extend定义,因此在构造实例化Control类的子类时,会默认执行initialize方法,在initialize方法中会将参数options设置挂载到实例对象上;

Control类的默认位置选项是topright,其值可能有 topleft, topright, bottomleft 或者 bottomright。

  1. 控件位置管理

Control类的位置管理主要通过两个函数getPosition和setPosition分别用于获取和设置控制的位置。

setPosition方法的原理是接受一个位置字符串,如上面的值之一,方法内部会先移除控件,重新赋值this.options.position,然后再将控件添加到地图上, 最后返回控件本身。

  1. 控件容器与生命周期

getContainer方法用于获取控件的HTML ELement。

Control类的生命周期方法就是addTo和remove,分别用于添加和移除控件。

  • addTo方法

addTo方法接受一个Map对象作为参数,首先会调用remove方法移除控件,然后将控件的位置信息赋值给this.options.position,接着获取控件的容器元素container,并根据位置信息将其添加到地图的相应位置。最后,为地图的unload事件添加一个监听器,当地图卸载时,会自动移除控件。

addTo方法中会调用子类的onAdd方法,该方法会在Control的子类中实现,用于创建具体控件的容器元素,并返回。

  • remove方法

remove方法用于移除控件,首先会判断控件是否已经添加到地图上,如果没有则直接返回控件本身。接着,会移除控件的容器元素,并调用子类的onRemove方法,该方法也会在Control的子类中实现,用于移除具体控件的容器元素。最后,为地图的unload事件移除监听器,移除控件。

  1. 焦点管理

Control类还包含一个_refocusOnMap方法,用于在地图上重新获取焦点。该方法接受一个事件对象作为参数,如果事件对象存在且屏幕坐标大于0,则会将地图的容器元素获取焦点。

# Map类扩展解析

Map类扩展主要包括以下内容:

  1. 控件管理 Map类扩展了addControl和removeControl方法,分别用于添加和移除控件。
  • addControl方法

addControl方法接受一个Control子类的实例作为参数,内部就是调用控件的addTo方法,该方法会在Control的子类中实现,用于将控件添加到地图的相应位置。

  • removeControl方法

removeControl方法同样也接受Control类的实例作为参数,然后调用实例的remove方法,并返回this。

  1. 控件容器初始化 Map类扩展了_initControlPos和_clearControlPos方法,分别用于初始化控件容器和清除控件容器。
  • _initControlPos方法

_initControlPos方法用于初始化控件容器,首先会创建一个名为_controlCorners的对象,用于存储控件的四个角的容器元素。然后,根据位置信息,创建四个角的容器元素,并将其添加到_controlContainer中。最后,将_controlContainer添加到地图的容器元素中。

  • _clearControlPos方法

_clearControlPos方法用于清除控件容器,首先会遍历_controlCorners对象,将其中的容器元素移除。然后,将_controlContainer移除,并删除_controlCorners和_controlContainer属性。

# 总结

Control基类是Leaflet中所有控件的基类,负责管理地图控件的创建、定位和生命周期。

  • Control类的实现主要包括控件位置管理、控件容器与生命周期、焦点管理等。
  • Map类扩展主要包括控件管理和控件容器初始化。
编辑 (opens new window)
上次更新: 2025/03/31, 01:38:11
PosAnimation位置动画介绍
Control.Scale

← PosAnimation位置动画介绍 Control.Scale→

最近更新
01
GeoJSON
05-08
02
Circle
04-15
03
CircleMarker
04-15
更多文章>
Theme by Vdoing | Copyright © 2024-2025 东流 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式