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

overflow-x: auto 使用鼠标实现横向滚动,区分触摸板和鼠标滚动事件的方法

假设一个 div 的滚动只设置了 overflow-x: auto 我们发现使用鼠标的滚轮是无法左右滚动的,但是使用笔记本电脑的触摸板,或者在移动设备上是可以滚动的。所以我们需要兼容一下鼠标的横向滚动功能。

我们可以监控 wheel 事件,然后根据位置来计算滚动的距离,不能使用 mousewheel 因为 mousewheel 事件在火狐浏览器并不支持,mousewheel 已经逐渐被 wheel 事件代替。

区分触摸板和鼠标滚轮

触摸板支持的横向滚动十分丝滑,如果不区分鼠标滚轮和触摸板,把所有的 wheel 事件都用新写的方法,那么使用触摸板滑动的时候体验很不好,容易左右抖动。这是因为触摸板的 wheel 事件触发的频率相对于鼠标滚轮高很多。所以我们要保留触摸板原生支持的横向滚动方法,然后重写一下鼠标触发的 wheel 事件。

下面是区分触摸板和鼠标 wheel 事件的方法。

 const checkIsTrackpad = e => {
    if (isSafari()) {
      return e.deltaMode === 0 && Math.floor(Math.abs(e.wheelDeltaY)) < 4
    }
    if (isFireFox()) {
      return (
        e.deltaMode === WheelEvent.DOM_DELTA_PIXEL ||
        (typeof e.MozInputSource !== 'undefined' && e.MozInputSource === 5)
      )
    }
    // 鼠标滚轮通常以 120 为步长
    return e.sourceCapabilities?.firesTouchEvents || (e.constructor.name === 'WheelEvent' && e.wheelDeltaY % 120 !== 0)
  }

所以一个 div 的横向滚动的方法如下:


const onMouseWheel = e => {
  // 触摸板滚动
  const checkIsTrackpad = e => {
    if (isSafari()) {
      return e.deltaMode === 0 && Math.floor(Math.abs(e.wheelDeltaY)) < 4
    }
    if (isFireFox()) {
      return (
        e.deltaMode === WheelEvent.DOM_DELTA_PIXEL ||
        (typeof e.MozInputSource !== 'undefined' && e.MozInputSource === 5)
      )
    }
    // 鼠标滚轮通常以 120 为步长
    return e.sourceCapabilities?.firesTouchEvents || (e.constructor.name === 'WheelEvent' && e.wheelDeltaY % 120 !== 0)
  }
  const isTrackPad = checkIsTrackpad(e)
  if (isTrackPad) {
    return
  }
  // 鼠标滚动
  e.preventDefault()
  const delta = e.deltaY || e.deltaX
  //  serviceScrollContentEle 是 设置为 overflow-x: auto 的 div
  serviceScrollContentEle.value.scrollLeft += delta * (e.shiftKey ? 3 : 2)
  if (!isScrolling) {
    isScrolling = true
    // 使用这个方法更好
    requestAnimationFrame(() => {
      isScrolling = false
    })
  }
}

相关文章:

  • 【自学笔记】Spring Boot框架技术基础知识点总览-持续更新
  • STM32-温湿度上传OneNET项目
  • 机器学习 - 衡量模型的特性
  • 合合信息2025届春季校园招聘全面启动!
  • 深入浅出机器学习:概念、算法与实践
  • 一篇搞懂vue3中如何使用ref、reactive实现响应式数据
  • Vue3+element UI:使用el-dialog时,对话框不出现解决方案
  • Mysql 迁移 dm 数据库
  • ip属地是电话号码吗怎么改
  • 企业知识管理平台重构数字时代知识体系与智能服务网络
  • 利用爬虫精准获取淘宝商品描述:实战案例指南
  • 腾讯云cloudstudio使用笔记(一)
  • ros通信与回调函数多线程应用
  • 基于Python+Vue开发的反诈视频宣传管理系统源代码
  • 一文详解U盘启动Legacy/UEFI方式以及GPT/MBR关系
  • MySQL八股学习笔记
  • 回不去的乌托邦
  • 网络通信 之综合布线(Integrated Cabling for Network Communication)
  • MATLAB在投资组合优化中的应用:从基础理论到实践
  • 新品!杰和科技国产化云终端VT32,实现办公“双安全”保障
  • 中期选举后第三势力成“莎拉弹劾案”关键,菲律宾权斗更趋复杂激烈
  • 临港新片区将新设5亿元启航基金:专门投向在临港发展的种子期、初创型企业
  • 手机表面细菌菌落总数可能比马桶高10倍,医生详解如何洗手
  • 奥古斯都时代的历史学家李维
  • 冰雹造成车损能赔吗?如何理赔?机构答疑
  • “异常”只停留在医院里,用艺术为“泡泡宝贝”加油