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.Scale
    • Control.Zoom
      • 概述
      • 源码分析
        • 源码实现
        • 源码详细介绍
      • 总结
    • Control.Attribution
    • Control.Layers
  • geometry

  • geo

  • layer

  • Map

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

Control.Zoom

# 概述

Control.Zoom是 Leaflet 地图库中**缩放控件(Zoom Control)**的实现,用于创建地图的放大/缩小按钮,并管理其交互逻辑。

# 源码分析

# 源码实现

Control.Zoom的源码实现如下:

export var Zoom = Control.extend({
  options: {
    options: "topleft",
    zoomInText: '<span aria-hidden="true">+</span>',
    zoomInTitle: "Zoom in",
    zoomOutText: '<span aria-hidden="true">&#x2212;</span>',
    zoomOutTitle: "Zoom out",
  },

  onAdd: function (map) {
    //创建容器和按钮
    var zoomName = "leaflet-control-zoom",
      container = DomUtil.create("div", zoomName + " leaflet-bar"),
      options = this.options;

    // 放大按钮
    this._zoomInButton = this._createButton(
      options.zoomInText,
      options.zoomInTitle,
      zoomName + "-in",
      container,
      this._zoomIn
    );
    // 缩小按钮
    this._zoomOutButton = this._createButton(
      options.zoomOutText,
      options.zoomOutTitle,
      zoomName + "-out",
      container,
      this._zoomOut
    );
    // 更新按钮状态
    this._updateDisabled();

    //监听地图缩放事件
    map.on("zoomend zoomlevelschange", this._updateDisabled, this);

    // 返回控件DOM元素
    return container;
  },
  onRemove: function (map) {
    // 解除监听事件
    map.off("zoomend zoomlevelschange", this._updateDisabled, this);
  },

  disable: function () {
    this._disabled = true;
    this._updateDisabled();
    return this;
  },

  enable: function () {
    this._disabled = false;
    this._updateDisabled();
    return this;
  },

  _zoomIn: function (e) {
    if (!this._disabled && this._map._zoom < this._map.getMaxZoom()) {
      this._map.zoomIn(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1));
    }
  },

  _zoomOut: function (e) {
    if (!this._disabled && this._map._zoom > this._map.getMinZoom()) {
      this._map.zoomOut(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1));
    }
  },

  _createButton: function (html, title, className, container, fn) {
    var link = DomUtil.create("a", className, container);
    link.innerHTML = html;
    link.href = "#";
    link.title = title;
    link.setAttribute("role", "button");
    link.setAttribute("aria-label", title);

    DomEvent.disableClickPropagation(link);
    DomEvent.on(link, "click", DomEvent.stop);
    DomEvent.on(link, "click", fn, this);
    DomEvent.on(link, "click", this._refocusOnMap, this);

    return link;
  },

  _updateDisabled: function () {
    var map = this._map,
      className = "leaflet-disabled";

    DomUtil.removeClass(this._zoomInButton, className);
    DomUtil.removeClass(this._zoomOutButton, className);
    this._zoomInButton.setAttribute("aria-disabled", "false");
    this._zoomOutButton.setAttribute("aria-disabled", "false");

    if (this._disabled || map._zoom === map.getMinZoom()) {
      DomUtil.addClass(this._zoomOutButton, className);
      this._zoomOutButton.setAttribute("aria-disabled", "true");
    }
    if (this._disabled || map._zoom === map.getMaxZoom()) {
      DomUtil.addClass(this._zoomInButton, className);
      this._zoomInButton.setAttribute("aria-disabled", "true");
    }
  },
});

Map.mergeOptions({
  zoomControl: true,
});

Map.addInitHook(function () {
  if (this.options.zoomControl) {
    this.zoomControl = new Zoom();
    this.addControl(this.zoomControl);
  }
});

export var zoom = function (options) {
  return new Zoom(options);
};
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

# 源码详细介绍

1.核心结构

  • Control.Zoom继承自Control类,Control类是 Leaflet 的基础控件类,提供控件通用的位置、容器管理等功能。
  • 提供了一个工厂函数导出zoom,允许用户通过L.control.zoom(options)创建一个缩放控件实例。

2.配置项

  • 可自定义:用户可通过传入 options 覆盖默认值,例如修改按钮图标或位置
options: {
  position: "topleft",       // 控件位置(如 topleft, bottomright)
  zoomInText: '+',           // 放大按钮的 HTML 内容
  zoomInTitle: "Zoom in",    // 放大按钮的提示文本
  zoomOutText: '−',          // 缩小按钮的 HTML 内容
  zoomOutTitle: "Zoom out"   // 缩小按钮的提示文本
}
1
2
3
4
5
6
7

3.生命周期方法

  • onAdd(map):控件添加到地图时调用

onAdd方法内部会调用DomUtil.create方法创建控件容器,以及调用内部方法_createButton方法创建控件按钮,然后监听地图缩放事件,更新按钮状态

  • onRemove(map):控件移除时调用

onRemove方法就干了一件事,就是解除绑定的事件监听

4.功能方法

  • 缩放控制

缩放控制包括_zoomIn和_zoomOut方法,分别表示放大和缩小操作,在调用内部方法_createButton时就会绑定对应的点击事件。有两点需要注意:

  • 加速控制:按住 Shift 键时,缩放幅度变为 3 倍(zoomDelta 默认是 1)

  • 边界检查:在最小/最大缩放级别时禁用对应按钮

  • 按钮创建

_createButton方法用于创建一个按钮,内部调用DomUtil.create方法创建按钮元素,然后设置按钮的 HTML 内容、标题、类名、事件监听等。还包括无障碍支持role='button'和aria-label。

  • 按钮状态更新

按钮状态更新包括样式控制和事件触发:

  • 样式控制:添加/移除 leaflet-disabled 类,改变按钮外观。

  • ​ 事件触发:当地图缩放级别变化(zoomend)或缩放范围变化(zoomlevelschange)时调用。

  • 禁用/启用 disable和enable方法用于禁用/启用缩放控件,内部调用_updateDisabled方法更新按钮状态。

5.默认配置

Map.mergeOptions:将默认配置项合并到Map类的options属性中。而Map.addInitHook的参数函数则会在地图初始化时执行,用于创建默认的缩放控件实例。

# 总结

Control.Zoom的缩放控件本质上是调用地图实例map的zoomIn和zoomOut方法实现,而默认的地图都会有一个缩放控件则和Map类的addInitHook方法有关。

编辑 (opens new window)
上次更新: 2025/04/01, 09:26:12
Control.Scale
Control.Attribution

← Control.Scale Control.Attribution→

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