浅谈wheel滚轮事件(兼容触摸板多次触发)
wheel 滚轮事件
一、事件说明
当滚动鼠标滚轮或操作其它类似输入设备时会触发滚轮事件
Tips:
- 使用触摸板触发该事件,由于系统的平滑处理,会触发多次该事件
- IE 下无法使用触摸板触发该事件
- 替换了已被弃用的非标准 mousewheel 和 DOMMousewheel 事件。
二、兼容性
桌面端
浏览器 | 版本 |
---|---|
Chrome | 61 |
Edge | 12 |
Firefox | 17 |
IE | 9 |
Opera | 48 |
Safari | 7 |
移动端
浏览器 | 版本 |
---|---|
WebView Android | 61 |
Chrome Android | 61 |
Firefox for Android | 17 |
Opera Android | 45 |
Safari on iOS | 7 |
Samsung Internet | 8 |
三、常规用法(不考虑触摸板的情况)
// wheel事件回调
const onWheel = useCallback(e => {console.log(e)},[]
);useEffect(() => {window.addEventListener('wheel', onWheel);return function () {window.removeEventListener('wheel', onWheel);};
}, []);
四、加上防抖
上面的做法虽然可以实现功能,但是每滚动一下就会处理一次逻辑,很浪费性能而且在IE上面还会导致滚动卡顿不流畅,这个时候就可以加上防抖的效果再尝试一下。
const { current} = useRef({isScroll: true, // 是否可以滚动timer: null, // setTimeout句柄delay: 300 // 防抖时间
})
// wheel事件回调
const onWheel = useCallback(e => {// 是否可以滚动,不写到setTimeout里面就可以先执行逻辑,在进行防抖,避免造成不跟手的情况if (current.isScroll) {current.isScroll = false;...}// 如果已经上次的防抖效果还没有释放,又触发了wheel回调,那么就取消上次的防抖效果if (current.timer) {clearTimeout(current.timer);}// 重新开始计算current.timer = setTimeout(() => {current.isScroll = true;}, current.delay);},[]
);useEffect(() => {window.addEventListener('wheel', onWheel);return function () {window.removeEventListener('wheel', onWheel);};
}, []);
五、考虑触摸板的情况
上面的那种方法,已经可以解决大部分的情况,但是如果防抖的时间设置的少于一定时间,用上触摸板之后就会发现,轻轻的滑动一次,wheel事件的处理逻辑就会被触发好多次。
这种情况产生的原因,根据网上的说法是似乎系统为了实现平滑滚动的效果还是其他原因,当你手指离开触摸板后wheel依然还会执行一段时间。
解决办法
- 增加防抖的延迟时间。这个办法虽然可以解决触摸板滑动一次触发多次wheel事件的问题,但是可能会造成正常的滚动时页面根本滚不动的问题(即在防抖的时间内又触发了一次)
- 判断本次wheel事件是由系统的平滑处理所产生还是由正常的滚动所产生的,但是wheel事件的回调当中并没有提供可以区分这两种情况的属性,这个时候只能找一下正常滚动时的回调属性和由系统的平滑处理产生的回调属性这两者有什么不同了。
根据对比可以发现,由系统的平滑处理所产生事件的移动距离基本都是小于100的,而且事件产生的时间间隔都很短,所以可以通过判断上次正常滚动的时间和本次事件产生的时间间隔还有本次事件的移动距离来判断,本次的事件是不是一次正常的滚动(并不是最优质的解决办法,还会有误判发生,但目前并没有想到更好的解决办法)。
// 获取时间戳(毫秒级别)
const getTime = useCallback(() => {return new Date().getTime();
}, []);const { current } = useRef({isScroll: true, // 是否可以正常的滚动scrollTime: null, // 上次切换的时间戳(毫秒级别)timer: null, // setTimeout句柄interval: 500, // 两次滑动之间的最小事件间隔distance: 100, // 有效滑动的最小距离delay: 400, // 防抖时间
});// wheel事件处理函数
const wheel = useCallback(e => {...},[]
);// wheel事件回调
const onWheel = useCallback(e => {const time = getTime();const y = e.deltaY; // 以垂直滚动为列if (current.scrollTime) {// 如果这次触发的时机跟上次切换的时机差大于一定时间,并且滑动距离大于一定距离,那么就认为是有效滑动if (time - current.scrollTime > current.interval &&Math.abs(y) >= current.distance) {// 触摸板滚动wheel(e);clearTimeout(current.timer);current.isScroll = false;current.scrollTime = time;}}if (current.isScroll) {// 正常滚动wheel(e);current.scrollTime = getTime();current.isScroll = false;}if (current.timer) {clearTimeout(current.timer);}current.timer = setTimeout(() => {current.isScroll = true;}, current.delay);},[]
);useEffect(() => {window.addEventListener('wheel', onWheel);return function () {window.removeEventListener('wheel', onWheel);};
}, []);
浅谈wheel滚轮事件(兼容触摸板多次触发)相关推荐
- onbeforeunload触发ajax,浅谈window.onbeforeunload() 事件调用ajax
经常有这样的需求,就是在离开某个web页面时,用户不一定点注销,这样会导致会话不能及时销毁.为实现用户离开页面时,自动注销功能,需要在web页面的onbeforeunload事件处理函数中发送注销命令 ...
- mac鼠标滚轮 触控板_如何在Mac上为滚轮而不是触摸板禁用自然滚动
mac鼠标滚轮 触控板 Does using a scroll wheel on your Mac feel-wrong? You're not alone. 在Mac上使用滚轮是否感觉--不对? 你 ...
- Javascript鼠标滚轮事件兼容写法
1.mousewheel事件(兼容opera,chrome,safari,IE) mousewheel事件对应的event对象包含一个wheelDelta属性.用户滚动鼠标滚轮时,wheelDelta ...
- 浅谈Vue 自定义事件——原理及用法
前言 在Vue 中,对HTML的原生事件做了支持.例如:click.focus.change等事件.除了原生事件外,Vue 还允许用户自定义事件. 什么是事件?什么是自定义事件? 在了解自定义事件前, ...
- 浅谈android的事件分发机制
一.点击事件介绍 在Android 的点击事件中我们涉及到ViewGroup类的三个方法: @Overridepublic boolean dispatchTouchEvent(MotionEvent ...
- 浅谈javascript的事件监听——音乐播放器的控制
javascript的事件 javascript是一门基于事件驱动的语言,当html页面中的元素触发一些动作时,可以执行相关的js代码. 1.常见事件 浏览器窗体事件 事件名 描述 onload 当窗 ...
- 文本框内容自动投影,浅谈C#中事件的写法与应用
C#中委托和事件,对应设计模式:Observe观察者模式 触发事件A的时候自动引起事件B的改变 有两个打开的窗体Form1,Form2 都有一个文本框控件TextBox Form1的文本框输入内容时, ...
- JS 浅谈JavaScript之事件
转载: https://www.cnblogs.com/wangjiming/p/9983023.html 一 简述JavaScript及其在浏览器中的地位 (一) 浏览器主要构成 虽然不同浏览器 ...
- 触摸板触摸屏禁止手指缩放,这么处理才行
禁止缩放 有天,辛苦做了个复杂操作功能的页面,上线后有用户反馈:很多功能使用不了.惊了,以为是哪里出了bug. 立马联系用户,才发现原来是用户使用笔记本电脑,没有禁用触控板,然后不小心碰到导致整个界面 ...
最新文章
- [转载红鱼儿]kbmmw 开发点滴:ErrorTable用法
- 企业库应用实践系列三:自定义构造函数
- Java核心技术点之集合框架
- 非负矩阵分解中基于L1和L2范式的稀疏性约束
- [APIO2013]机器人(DP+SPFA最短路)
- 怎么查看数据库服务器型号,如何查看服务器数据库类型
- Mac下使用Wine安装PowerDesigner15
- 纵横安卓刷机界的CM,如今转行做无人车了,还获得了加州路测许可
- oracle删除数据库中的所有数据的拼接语句
- 试试这些方法,误删文件怎么恢复?
- sentencePiece入门小结
- 膜拜性转帖: C++11有关的(现在用的编译器都是不太支持C++11的)
- VS2010中使用AnkhSvn
- 普歌-Vue 封装防刷新考试倒计时组
- 快速关闭SELinux
- 软件项目开发中的百分之九十效应
- ubuntu远程访问win7登录后语言为繁体字的解决办法
- 一位前BAT面试官,详聊进入BAT的面试经验
- 常用User-Agent大全
- 实时即未来,车联网项目之远程诊断实时故障分析【七】
热门文章
- 计算机音乐创作比赛作品,2015年(第八届)中国大学生计算机设计大赛“计算机音乐创作类”决赛在我院隆重开幕...
- 中间人攻击——ARP欺骗的原理、实战及防御(转载)
- Android9.0解决WIFI已连接,但图标显示不能上网问题
- 喜欢一个女生应该如何表达
- c/c++时间操作函数总结
- Tcp三次握手连接梳理
- (转)一个睡五分钟等于六个钟头的方法
- 佛教 佛教图书 佛教资料下载 佛教都市
- SSM-框架整合(简介+源码)
- C++:友元(看这一篇就够了)