当前位置: 首页 > news >正文

源码分析之Leaflet中dom模块DomEvent.DoubleTap的实现原理

概述

DomEvent.DoubleTap模块是Leaflet中用于模拟双击(dbclick)事件的模块,主要解决移动端浏览器对双击事件支持不完善或延迟的问题,同时避免与标签(<label>)关联的表单元素误触发。

源码分析

源码实现如下

DomEvent.DoubleTap的源码实现如下:

function makeDblclick(event) {
  var newEvent = {},
    prop,
    i;
  // 复制原始事件的所有属性(包括方法)  
  for (i in event) {
    prop = event[i];
    newEvent[i] = prop && prop.bind ? prop.bind(event) : prop;
  }
  event = newEvent;

  // 修改事件类型为dbclick,并标记为模拟事件
  newEvent.type = "dblclick";
  newEvent.detail = 2;//表示双击
  newEvent.isTrusted = false;//非浏览器原生触发
  newEvent._simulated = true; //Leaflet内部标记
  return newEvent;
}

var delay = 200;
export function addDoubleTapListener(obj, handler) {
  // 直接监听原生dbclick事件(桌面浏览器)
  obj.addEventListener("dblclick", handler);

  var last = 0,
    detail;
  function simDblclick(e) {
    //忽略非单次点击事件
    if (e.detail !== 1) {
      detail = e.detail;
      return;
    }

    // 过滤鼠标事件,仅处理触控或笔触
    if (
      e.pointerType === "mouse" ||
      (e.sourceCapabilities && !e.sourceCapabilities.firesTouchEvents)
    ) {
      return;
    }

    // 检查事件路径,避免label元素误触发
    var path = DomEvent.getPropagationPath(e);
    if (
      path.some(function (el) {
        return el instanceof HTMLLabelElement && el.attributes.for;
      }) &&
      !path.some(function (el) {
        return (
          el instanceof HTMLInputElement || el instanceof HTMLSelectElement
        );
      })
    ) {
      return;
    }

    // 计算事件间隔,模拟双击
    var now = Date.now();
    if (now - last <= delay) {
      detail++;
      if (detail === 2) {
        handler(makeDblclick(e)); //触发自定义dbclick事件
      }
    } else {
      detail = 1;
    }
    last = now;
  }
  
  // 监听click事件,通过时间间隔判断双击
  obj.addEventListener("click", simDblclick);

  return {
    dblclick: handler,
    simDblclick: simDblclick,
  };
}

export function removeDoubleTapListener(obj, handlers) {
  obj.removeEventListener("dblclick", handlers.dblclick);
  obj.removeEventListener("click", handlers.simDblclick);
}

源码详解

  1. makeDbclick(event)函数:构造模拟的双击事件
  • ​目的:克隆原始事件并转换为自定义的 dblclick 事件,用于模拟双击行为。
  • 关键点
    • ​属性复制:遍历原始事件属性,若属性是方法(如 preventDefault),则绑定到原始事件上下文。
    • 标记为非可信事件isTrusted: false 表示此事件由脚本生成,而非用户直接操作触发。
  1. addDoubleTapListener(obj, handler)函数:添加双击监听
  • ​核心逻辑
    1. ​双重监听

      • 直接监听原生 dblclick(桌面浏览器有效)。
      • 通过 click 事件模拟移动端双击(simDblclick)。
    2. 过滤非触控事件

      • pointerType === 'mouse':排除鼠标操作。
      • sourceCapabilities.firesTouchEvents:仅处理触控或笔触(Chrome 特性)。
    3. 避免 <label> 误触发

      • 若事件路径中存在关联 <label for> 但无对应表单元素(如 <input>),则忽略点击。
    4. 时间间隔判断:

      • 两次 click 间隔小于 200ms 视为双击,触发自定义 dblclick 事件。
  1. removeDoubleTapListener(obj, handlers)函数:移除双击监听
  • ​目的:移除之前通过addDoubleTapListener添加的 dblclicksimDblclick 事件监听器。

  • 关键点:需传入之前返回的handles对象,确保移除正确的监听函数。

关键设计思想

  1. 移动端兼容性
    移动端浏览器通常不直接支持dbclick事件,通过快速连续点击(click)模拟双击行为

  2. 避免冲突:

    • 过滤 <label> 元素点击,防止其关联的表单元素(如复选框)被误操作。
    • 区分触控和鼠标事件,避免重复处理。
  3. 性能优化:

    • 使用 200ms 间隔判断双击,平衡响应速度和误触概率。
    • 通过 DomEvent.getPropagationPath(e) 获取事件传播路径,精确控制事件逻辑。

使用场景

  • ​地图双击缩放:用户快速双击地图时,触发放大地图的操作。
  • 移动端手势支持:在触控设备上实现与桌面浏览器一致的双击交互。

潜在问题与注意事项

  1. 事件可信度
    模拟的 dblclick 事件 isTrusted: false,某些安全策略可能限制其行为(如阻止默认动作)。

  2. ​时间间隔敏感性

200ms 的间隔可能导致部分用户操作未被识别为双击,需根据实际需求调整。

  1. 浏览器兼容性
  • sourceCapabilities 是 Chrome 特有属性,其他浏览器可能需额外兼容处理。
  • DomEvent.getPropagationPath 是 Leaflet 内部方法,用于获取事件传播路径(等价于 e.composedPath())。

总结

  • 核心功能:通过监听快速连续的 click 事件模拟 dblclick,解决移动端兼容性问题。
  • 设计亮点
    • 双重事件监听(原生 + 模拟)兼顾不同环境。
    • 路径过滤避免
    • 严格区分触控与鼠标事件。
  • 适用场景:需要跨平台支持双击交互的 Web 应用(尤其是地图库)。

相关文章:

  • STM32标准库之I2C示例代码
  • mac系统conda的python环境下安装uWSGI报缺少libpython3.9.a问题解决方法
  • Linux:gsd-account进程异常内存泄漏排查
  • 一个免费 好用的pdf在线处理工具
  • Jmeter旧版本如何下载
  • 接口自动化测试框架详解
  • 永磁同步电机模型第三篇之两相电机坐标变换
  • SolidWorks使用显卡教程
  • struts1+struts2项目兼容升级到了spring boot 2.7
  • Blender标注工具
  • 【Python】超详细实例讲解python多线程(threading模块)
  • SpringBoot入门-(1) Maven【概念+流程】
  • UNIX网络编程笔记:套接字
  • C#通过API接口返回流式响应内容---SignalR方式
  • 小科普《DNS服务器》
  • 用短说社区打造你的专属游戏社区
  • FreeRTOS列表和列表项
  • flink 写入es的依赖导入问题(踩坑记录)
  • 高并发下保证接口幂等性
  • vscode终端不识别npm 无法解析npm
  • 广西北部湾国际港务集团副总经理潘料庭接受审查调查
  • KPL“王朝”诞生背后:AG和联赛一起迈向成熟
  • 沈阳卫健委通报“健康证”办理乱象:涉事医院已被立案查处
  • 智能手表眼镜等存泄密隐患,国安部提醒:严禁在涉密场所使用
  • 民企老板被错羁212天续:申请国赔千万余元,要求恢复名誉赔礼道歉
  • 香港将展“天方奇毯”,从地毯珍品看伊斯兰艺术