Jinuss's blog Jinuss's blog
首页
  • 源码合集

    • Leaflet源码分析
    • Openlayers源码合集
    • vue3源码
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

东流

Web、WebGIS技术博客
首页
  • 源码合集

    • Leaflet源码分析
    • Openlayers源码合集
    • vue3源码
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 框架

  • core模块

  • dom模块

  • control

  • geometry

  • geo

  • layer

  • Map

    • Map类
    • Map类扩展方法之BoxZoom
    • Map类扩展方法之DoubleClickZoom
    • Map类扩展方法之Drag
    • Map类扩展方法之Keyboard
    • Map类扩展方法之ScrollWheelZoom
      • 概览
      • 源码分析
        • 源码实现
        • 源码详细解析
        • 配置选项
        • 核心模块ScrollWheelZoom
        • 关键设计亮点
      • 总结
    • Map类扩展方法之TapHold
    • Map类扩展方法之TouchZoom
  • 《Leaflet源码》笔记
  • Map
东流
2025-04-07
目录

Map类扩展方法之ScrollWheelZoom

# 概览

ScrollWheelZoom是Map类的扩展方法之一,用于实现鼠标滚轮缩放地图的功能。它通过监听鼠标滚轮事件,根据滚轮滚动的方向和距离,调整地图的缩放级别。

# 源码分析

# 源码实现

ScrollWheelZoom的源码实现如下:

Map.mergeOptions({
  scrollWheelZoom: true, // 默认启用滚轮缩放
  wheelDebounceTime: 40,  // 防抖时间,单位:毫秒
  wheelPxPerZoomLevel: 60, // 每缩放一级需要的像素滚动量
});

export var ScrollWheelZoom = Handler.extend({
  addHooks: function () {
    DomEvent.on(this._map._container, "wheel", this._onWheelScroll, this);
    this._delta = 0; // 累计滚动量,累加器
  },
  removeHooks: function () {
    DomEvent.off(this._map._container, "wheel", this._onWheelScroll, this);
  },
  _onWheelScroll: function (e) {
    // 调用`DomEvent.getWheelDelta`方法获取鼠标滚动增量

    var delta = DomEvent.getWheelDelta(e);
    var debounce = this._map.options.wheelDebounceTime;
    
    this._delta += delta;
    
    // 记录当前鼠标位置(用于以鼠标为中心进行缩放)
    this._lastMousePos = this._map.mouseEventToContainerPoint(e);

    // 防抖逻辑
    if (!this._startTime) {
      this._startTime = +new Date();
    }
    var left = Math.max(debounce - (+new Date() - this._startTime), 0);

    clearTimeout(this._timer);
    this._timer = setTimeout(Util.bind(this._performZoom, this), left);
    
    // 阻止默认滚动行为
    DomEvent.stop(e);
  },
  _performZoom: function () {
    var map = this._map,
      zoom = map.getZoom(),
      snap = this._map.options.zoomSnap || 0; //缩放步长

    map._stop();
    // 计算缩放变化量,应用平滑曲线
    var d2 = this._delta / (this._map.options.wheelPxPerZoomLevel * 4),
      d3 = (4 * Math.log(2 / (1 + Math.exp(-Math.abs(d2))))) / Math.LN2,
      d4 = snap ? Math.ceil(d3 / snap) * snap : d3,
      delta = map._limitZoom(zoom + (this._delta > 0 ? d4 : -d4)) - zoom;
    //重置状态累加器
    this._delta = 0;
    this._startTime = null;

    // 应用缩放
    if (!delta) {
      return;
    }

    if (map.options.scrollWheelZoom === "center") {
      map.setZoom(zoom + delta); //以地图为中心缩放
    } else {
      map.setZoomAround(this._lastMousePos, zoom + delta);//以鼠标位置为中心缩放
    }
  },
});

Map.addInitHook("addHandler", "scrollWheelZoom", ScrollWheelZoom);
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

# 源码详细解析

# 配置选项

通过Map.mergeOptions将滚轮缩放的默认配置合并到地图选项中,用户可通过map.options覆盖。

# 核心模块ScrollWheelZoom

  1. 事件钩子管理

    • 监听wheel事件:绑定到地图容器的滚轮事件
    • 初始化状态:重置累计滚动量_delta
  2. 滚轮事件处理(_onWheelScroll)

    • 防抖机制:通过wheelDebounceTime(默认40ms)合并高频滚动事件,避免过渡触发缩放
    • 关键变量:
      • delta:累计滚动量,正值为放大,负值为缩小
      • _lastMousePos:记录当前鼠标位置,用于以鼠标为中心进行缩放
  3. 执行缩放(_performZoom)

    • 缩放算法
      • 通过wheelPxPerZoomLevel(默认60px)控制灵敏度,滚动60px对应一级缩放
      • 使用Sigmoid函数平滑滚动量,避免缩放突变
      • 对齐zoomSnap,实现平滑的缩放步长
    • 缩放模式
      • center:以地图为中心进行缩放
      • 默认模式:以鼠标位置为中心进行缩放

# 关键设计亮点

​1. ​防抖优化​​

通过 wheelDebounceTime 避免高频滚动导致的性能问题,同时保持操作流畅性。

  1. ​​非线性滚动处理​​ 使用 Sigmoid 函数转换滚动量为缩放级别,使快速滚动时缩放速度逐渐趋缓。 ​​
  2. 支持多种配置​​
    • wheelPxPerZoomLevel:调整滚动灵敏度(值越小越敏感)。
    • zoomSnap:强制对齐缩放级别(如 0.5 级步进)。 ​
  3. ​焦点缩放模式​​ 通过 scrollWheelZoom: "center" 可切换为固定中心缩放。

# 总结

​ScrollWheelZoom 是 Leaflet 中实现鼠标滚轮缩放功能的核心模块,通过平滑的滚动处理和灵活的配置选项,提供了用户友好的地图缩放体验。它在用户操作时保持了流畅性,同时支持多种缩放模式,为用户提供了更多的交互方式。

编辑 (opens new window)
上次更新: 2025/04/16, 05:17:33
Map类扩展方法之Keyboard
Map类扩展方法之TapHold

← Map类扩展方法之Keyboard Map类扩展方法之TapHold→

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