Control.Scale
# 概述
Control.Scale
是一个用于显示地图比例尺的控件,是 Leaflet 中实现比例尺控件的核心逻辑,用于在地图上动态显示公制(米/千米)和英制(英尺/英里)的比例尺。
# 源码分析
# 源码实现
Control.Scale
的源码实现如下:
export var Scale = Control.extend({
options: {
position: "bottomleft", // 控件的位置
maxWidth: 100, // 控件的最大宽度 (像素)
metric: true, // 是否显示公制比例尺 米/千米
imperial: true, // 是否显示英制比例尺 英尺/英里
updateWhenIdle: false, // 是否在地图空闲时更新比例尺
},
onAdd: function (map) {
var className = "leaflet-control-scale",
container = DomUtil.create("div", className), //创建容器
options = this.options;
// 添加公制/英制比例尺元素
this._addScales(options, className + "-line", container);
// 监听地图移动事件,动态更新比例尺
map.on(options.updateWhenIdle ? "moveend" : "move", this._update, this);
map.whenReady(this._update, this); // 初始化时更新
return container;
},
onRemove: function (map) {
// 移除监听事件
map.off(
this.options.updateWhenIdle ? "moveend" : "move",
this._update,
this
);
},
_addScales: function (options, className, container) {
if (options.metric) {
this._mScale = DomUtil.create("div", className, container);
}
if (options.imperial) {
this._iScale = DomUtil.create("div", className, container);
}
},
_update: function () {
var map = this._map,
y = map.getSize().y / 2;
// 计算地图上maxWidth像素对应的实际距离(单位:米)
var maxMeters = map.distance(
map.containerPointToLatLng([0, y]),
map.containerPointToLatLng([this.options.maxWidth, y])
);
this._updateScales(maxMeters);
},
_updateScales: function (maxMeters) {
if (this.options.metric && maxMeters) {
this._updateMetric(maxMeters);
}
if (this.options.imperial && maxMeters) {
this._updateImperial(maxMeters);
}
},
_updateMetric: function (maxMeters) {
var meters = this._getRoundNum(maxMeters),
label = meters < 1000 ? meters + " m" : meters / 1000 + " km";
this._updateScale(this._mScale, label, meters / maxMeters);
},
_updateImperial: function (maxMeters) {
var maxFeet = maxMeters * 3.2808399,
maxMiles,
miles,
feet;
if (maxFeet > 5280) {
maxMiles = maxFeet / 5280;
miles = this._getRoundNum(maxMiles);
this._updateScale(this._iScale, miles + " mi", miles / maxMiles);
} else {
feet = this._getRoundNum(maxFeet);
this._updateScale(this._iScale, feet + " ft", feet / maxFeet);
}
},
_updateScale: function (scale, text, ratio) {
scale.style.width = Math.round(this.options.maxWidth * ratio) + "px";
scale.innerHTML = text;
},
_getRoundNum: function (num) {
var pow10 = Math.pow(10, (Math.floor(num) + "").length - 1),
d = num / pow10;
d = d >= 10 ? 10 : d >= 5 ? 5 : d >= 3 ? 3 : d >= 2 ? 2 : 1;
return pow10 * d;
},
});
export var scale = function (options) {
return new Scale(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
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
# 源码详细分析
# 类定义与选项
继承自
Control
: 继承自Control
基类类,用于创建可添加到地图上的控件。核心配置项:通过
metric
和imperial
控制比例尺单位显示
# 控件生命周期方法
onAdd
:控件添加到地图时触发
onAdd
方法主要用于创建比例尺控件的 DOM 元素,并将其添加到地图容器中。
onRemove
:控件从地图移除时触发
onRemove
方法就是清理事件监听,可以防止内存泄漏。
# 核心逻辑方法
_addScales
:创建公制/英制比例尺 DOM 元素
_addScales
方法根据配置项创建公制和英制比例尺的 DOM 元素。
_update
:更新比例尺的核心方法
_update
方法的核心逻辑就是通过map.distance
方法计算当前视图下maxWidth
像素对应的实际距离(基于地图投影)。
_updateScales
:根据实际距离更新比例尺
_updateScales
方法根据实际距离计算公制和英制比例尺的显示内容,并调用_updateScale
方法更新比例尺的 DOM 元素。
_updateMetric
:更新公制比例尺_updateMetric
方法根据实际距离计算公制比例尺的显示内容,并调用_updateScale
方法更新比例尺的 DOM 元素。_updateImperial
:更新英制比例尺_updateImperial
方法根据实际距离计算英制比例尺的显示内容,并调用_updateScale
方法更新比例尺的 DOM 元素。
# 单位更新逻辑
- 公制单位更新
_updateMetric
- 逻辑:若
maxMeters < 1000
显示米(m),否则显示千米(km)。 - 示例:若
maxMeters = 500
,则显示500 m
;若maxMeters = 1500
,则显示1.5 km
。
- 英制单位更新
_updateImperial
- 逻辑:若
maxMeters > 5280
,则显示英里(mi),否则显示英尺(ft)。 - 换算公式:
1 米 ≈ 3.28084 英尺
,1 英里 = 5280 英尺
# 辅助方法
_updateScale
:更新比例尺的 DOM 元素
- 功能:根据比例尺的比例更新比例尺的宽度和显示内容。
- 参数:
scale
:比例尺的 DOM 元素。text
:比例尺的显示内容。ratio
:比例尺的比例,用于计算比例尺的宽度。
_getRoundNum
:获取合适的显示数字
- 功能:根据比例尺的实际距离,返回合适的显示数字。
- 参数:
num
:比例尺的实际距离。
# 工厂函数
简化控件的创建,例如 L.control.scale({ metric: true })
。
# 总结
- 动态更新:比例尺会随地图缩放/移动自动重新计算。
- 跨单位支持:同时处理公制和英制单位,且自动选择合适单位(如米 → 千米,英尺 → 英里)。
- 数值优化:通过
_getRoundNum
避免显示复杂小数(如1.333 km
)。 - 性能优化:通过
updateWhenIdle
避免频繁更新
编辑 (opens new window)
上次更新: 2025/04/03, 07:19:02