Skip to content

控件

本文档涵盖 Leaflet 中的控件系统,它提供定位在地图角落的 UI 小部件。它解释了 Control 基类、定位系统、生命周期管理以及创建自定义控件的模式。关于地图交互处理器(拖拽、缩放、键盘)的信息,请参阅 地图交互处理器

控件架构

Control 类为 UI 小部件提供基础实现,这些小部件定位在地图的固定位置(通常在角落)。与图层不同,控件不参与地理坐标系统,而是锚定到地图容器的边缘。

SVG
100%

关键区别:控件扩展 Class,而不是 Layer。它们不参与图层系统,无论缩放级别或 pane 配置如何,始终可见。

定位系统

控件定位在地图的四个角落容器之一中。定位系统在创建地图时初始化,并为每个角落提供专用的 DOM 容器。

角落位置

位置字符串位置默认控件
'topleft'左上角缩放控件
'topright'右上角(如果未指定则为默认位置)
'bottomleft'左下角比例尺控件
'bottomright'右下角归属控件
SVG
100%

实现细节:地图通过 _initControlPos() 在初始化期间创建四个角落容器。每个角落都是一个带有 CSS 类的 <div> 元素,通过 flexbox 或绝对定位处理定位。

Control 基类

Control 类提供定位和生命周期管理的核心功能。所有控件必须实现 onAdd 方法,并可选实现 onRemove

构造函数和选项

// 默认选项
{
  position: 'topright'  // 初始角落位置
}

构造函数接受一个选项对象,使用 Util.setOptions() 与默认值合并。

核心方法

方法描述返回
getPosition()返回当前位置字符串string
setPosition(position)更改控件的位置this
getContainer()返回控件的 DOM 元素HTMLElement
addTo(map)将控件添加到地图this
remove()从其地图移除控件this

位置更改行为:当调用 setPosition() 时,控件从其当前角落移除(如果在地图上),并重新添加到新角落。这确保正确的 DOM 顺序和 CSS 应用。

控件生命周期

控件在被添加到地图或从地图移除时遵循特定的生命周期模式。

SVG
100%

生命周期方法

onAdd(map: LeafletMap): HTMLElement (必需)

  • 必须由子类实现
  • 应该创建并返回控件的容器 DOM 元素
  • 应该根据需要向地图或 DOM 元素添加事件监听器
  • 在控件添加到地图时调用

onRemove(map: LeafletMap): void (可选)

  • 应该清理事件监听器和资源
  • 在控件从地图移除时调用
  • 如果控件不需要清理则不需要

插入顺序:具有 'bottom' 位置的控件通过 insertBefore 插入到其角落容器的开头,而 'top' 位置则附加到末尾。这确保正确的视觉堆叠顺序。

地图集成

地图通过专用方法和 DOM 结构为托管控件提供基础设施。

地图方法

SVG
100%

控件容器结构:地图在初始化期间创建单个控件容器(_controlContainer),其中容纳所有四个角落容器(_controlCorners)。此结构由 _initControlPos() 创建,并在地图销毁时由 _clearControlPos() 清理。

角落容器创建

_initControlPos() 方法创建角落基础设施:

  1. 创建带有类 'leaflet-control-container' 的主控件容器
  2. 创建四个角落 div,每个都有两个 CSS 类用于定位:
    • 垂直:'leaflet-top''leaflet-bottom'
    • 水平:'leaflet-left''leaflet-right'
  3. _controlCorners 对象中存储引用,键为:'topleft''topright''bottomleft''bottomright'

内置控件

Leaflet 包括几个扩展 Control 基类的内置控件实现:

控件用途默认位置
Control.Zoom放大/缩小按钮'topleft'
Control.Attribution版权和数据归属'bottomright'
Control.Layers底图和覆盖图层的图层切换器'topright'
Control.Scale显示地图比例的比例尺'bottomleft'

注意:这些内置控件的实现文件未包含在提供的源代码中,但它们都遵循相同的模式,即扩展 Control 并实现 onAdd() 和可选的 onRemove()

创建自定义控件

自定义控件遵循基于 Control 基类的一致模式。

基本模式

SVG
100%

实现要求

必需方法:onAdd(map)

  • 必须返回表示控件的 HTMLElement
  • 应该为控件的 UI 创建 DOM 元素
  • 应该向地图或 DOM 元素附加事件监听器
  • 接收地图实例作为参数

可选方法:onRemove(map)

  • 应该移除在 onAdd 中添加的事件监听器
  • 应该清理任何资源或定时器
  • 接收地图实例作为参数

辅助功能辅助:_refocusOnMap(e)

  • 可用于在控件交互后将焦点移回地图
  • 排除键盘发起的点击(位置 0,0)以将焦点保持在控件上以辅助功能
  • 可在控件事件处理器中使用

示例结构

自定义控件通常遵循此结构:

  1. 类定义:扩展 Control
  2. 默认选项:通过 setDefaultOptions() 的静态块设置
  3. 初始化:可选的 initialize() 方法用于构造函数逻辑
  4. DOM 创建onAdd() 创建并返回控件的容器
  5. 事件绑定:向地图事件或控件 UI 附加监听器
  6. 清理onRemove() 移除监听器并清理资源

位置选项:自定义控件继承基类的 position 选项,允许用户将控件放置在任何角落。

控件与图层比较

理解控件和图层之间的区别对于选择正确的抽象很重要:

方面控件图层
基类Control 扩展 ClassLayer 扩展 Evented
定位固定到地图角落地理坐标
DOM 位置控件容器中的控制角落Panes(tilePane、overlayPane 等)
缩放行为始终以相同大小可见可能缩放或有缩放限制
主要用途UI 小部件和工具地图数据和地理要素
集成map.addControl() / control.addTo()map.addLayer() / layer.addTo()
必需方法onAdd(map): HTMLElementonAdd(map): void
归属不适用getAttribution() 用于归属控件

关键洞察:控件是用于与地图本身交互的 UI 元素,而图层代表要在地图上显示的地理数据。为工具和窗口小部件选择 Control,为数据可视化选择 Layer

技术细节

DOM 结构

当控件添加到地图时,它们创建特定的 DOM 层次结构:

map._container (地图容器)
└── map._controlContainer (类: leaflet-control-container)
    ├── map._controlCorners['topleft'] (类: leaflet-top leaflet-left)
    │   └── control._container (类: leaflet-control)
    ├── map._controlCorners['topright'] (类: leaflet-top leaflet-right)
    ├── map._controlCorners['bottomleft'] (类: leaflet-bottom leaflet-left)
    └── map._controlCorners['bottomright'] (类: leaflet-bottom leaflet-right)
        └── control._container (类: leaflet-control)

类分配

每个控件的容器元素自动接收 CSS 类 'leaflet-control',它为控件提供默认样式(通常包括背景、边框和内边距)。

自动清理

控件在地图触发 'unload' 事件时自动注册清理。这确保在地图销毁时正确移除控件,防止内存泄漏。