您的位置:首页 > 其它

手持设备点击响应速度,鼠标事件与touch事件的那些事

2016-05-26 17:12 489 查看

前言

现在一直在做移动端的开发,这次将单页应用的网页内嵌入了app,于是老大反映了一个问题:
app应用点击响应慢!
我开始不以为然,于是拿着网页版的试了试,好像确实有一定延迟,于是开始了研究,最后选择了touch取代鼠标事件

但是,touch事件取代mouse事件,还是有一定问题的,据说网上问题很多,因为两者之间还是有一定差异
而且如果完全使用touch事件,对自动化测试的同事来说,他们的系统根本不支持touch事件,再者我们平时网页开发也不方便
所以,了解鼠标事件与touch事件的区别,探讨鼠标事件与touch事件的兼容也是有必要的,于是我们开始今天的学习吧
PS:这里使用zepto框架,懒得自己搞了......

事件差异

鼠标事件

首先,我们来看看鼠标事件相关吧:

View Code

测试地址

http://sandbox.runjs.cn/show/7tyo48bf

各位自己运行看看差异吧

简单扩展touch事件

touch没有click事件,于是有zepto搞了个tap事件,我们这里先来简单模拟一下,再看源码怎么干的

1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2 <html xmlns="http://www.w3.org/1999/xhtml">
3 <head>
4     <title></title>
5     <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
6     <script id="others_zepto_10rc1" type="text/javascript" class="library" src="http://sandbox.runjs.cn/js/sandbox/other/zepto.min.js"></script>
7 </head>
8 <body>
9     <div id="d" style="position: absolute; top: 50px; left: 50px; width: 100px; height: 100px;
10         border: 1px solid black;">滑动我
11     </div>
12 </body>
13 <script type="text/javascript">
14 var log = function (msg) {
15     console.log(msg);
16 };
17 var d = $('body');
18
19 var touchEvents = function (el, type, func) {
20     this.long = 400; //用于设置长点击阀值
21     this.el = el || document;
22     this.func = func || function () { };
23     this.type = type || 'tap';
24     this.mouseData = {
25         sTime: 0,
26         eTime: 0,
27         sX: 0,
28         eX: 0,
29         sY: 0,
30         eY: 0
31     };
32     this.addEvent();
33
34 };
35 touchEvents.prototype = {
36     constructor: touchEvents,
37     addEvent: function () {
38         var scope = this;
39         this.startFn = function (e) {
40             scope.touchStart.call(scope, e);
41         };
42         this.moveFn = function (e) {
43             scope.touchMove.call(scope, e);
44         };
45         this.endFn = function (e) {
46             scope.touchEnd.call(scope, e);
47         };
48         this.el.addEventListener('touchstart', this.startFn);
49         //此处可以换成这样
50         //            document.addEventListener('touchmove', this.touchMove);
51         this.el.addEventListener('touchmove', this.moveFn);
52         this.el.addEventListener('touchend', this.endFn);
53     },
54     removeEvent: function () {
55         this.el.removeEventListener('touchstart', this.touchStart);
56         this.el.removeEventListener('touchmove', this.touchMove);
57         this.el.removeEventListener('touchend', this.touchEnd);
58     },
59     touchStart: function (e) {
60         var pos = e.changedTouches[0];
61         this.mouseData.sTime = new Date().getTime();
62         this.mouseData.sX = pos.pageX;
63         this.mouseData.sY = pos.pageY;
64     },
65     touchMove: function (e) {
66         e.preventDefault();
67         return false;
68     },
69     touchEnd: function (e) {
70         var pos = e.changedTouches[0];
71         this.mouseData.eTime = new Date().getTime();
72         this.mouseData.eX = pos.pageX;
73         this.mouseData.eY = pos.pageY;
74         this.onTouchEnd(e);
75     },
76     onTouchEnd: function (e) {
77         if (this.type == this._getDir()) {
78             this.func(e, this);
79         }
80     },
81     _getDir: function () {
82         //时间间隔,间隔小于100都认为是快速,大于400的认为是慢速
83         var timeLag = this.mouseData.eTime - this.mouseData.sTime;
84         var dir = 'swipe';
85         if (timeLag > this.long) dir = 'longSwipe';
86         if (this.mouseData.sX == this.mouseData.eX && this.mouseData.sY == this.mouseData.eY) {
87             dir = 'tap';
88             if (timeLag > this.long) dir = 'longTap';
89         } else {
90             if (Math.abs(this.mouseData.eY - this.mouseData.sY) > Math.abs(this.mouseData.eX - this.mouseData.sX)) {
91                 dir = this._getUDDir(dir);
92             } else {
93                 dir = this._getLRDir(dir);
94             }
95         }
96         log(dir);
97         d.append($('<div>间隔:' + timeLag + ', 方向:' + dir + '</div>'));
98         return dir;
99     },
100     //单独用于计算上下的
101     _getUDDir: function (dir) {
102         if (this.mouseData.eY - this.mouseData.sY > 0) dir += 'Down';
103         if (this.mouseData.eY - this.mouseData.sY < 0) dir += 'Up';
104         return dir;
105     },
106     //计算左右
107     _getLRDir: function (dir) {
108         if (this.mouseData.eX - this.mouseData.sX > 0) dir += 'Right';
109         if (this.mouseData.eX - this.mouseData.sX < 0) dir += 'Left';
110         return dir;
111     }
112 };
113
114 new touchEvents(d[0], 'tap', function (e) {
115     log(arguments);
116 });
117
118 </script>
119 </html>


这个代码基本可用了,但是使用上不是很方便,我们这里就不关注了,下面我们来看看zepto的代码和兼容问题

zepto的touch与兼容

先上zepto源码,一看就知道我写的有多不行啦!

按 Ctrl+C 复制代码

按 Ctrl+C 复制代码

touch对象与上面mouseData功效相同,记录一些属性
delta 用于记录两次点击的间隔,间隔短就是双击
swipeDirection 函数与_getDir _getUDDir _getLRDir 功能相似,只不过代码更为简练,并且真正的私有化了
63行代码开始,若是代码移动过便是划屏,否则就是点击,这点我也没考虑到
73行,否则就应该是点击,这里并且判断是否存在结束时间,代码比较健壮,做了双击或者快速点击的判断

开始兼容

zepto代码我自然没有资格去评说,现在我们来看看他的兼容问题

PS:我这里很水,不太敢动源码,就加一个tap判断,因为也只是用了这个,具体大动手脚的事情,我们后面再做

这样做事因为,我们的项目主要是把click改成了tap事件,导致页面很多功能不可用

1 ['swipe', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown', 'doubleTap', 'tap', 'singleTap', 'longTap'].forEach(function (m) {
2   //兼容性方案处理,以及后期资源清理,如果为假时候,就触发点击事件
3     var isTouch = 'ontouchstart' in document.documentElement;
4     if(m === 'tap' && isTouch === false) {
5         $.fn[m] = function (callback) { return this.bind('click', callback) }
6     } else {
7         $.fn[m] = function (callback) { return this.bind(m, callback) }
8     }
9   })


我就干了这么一点点事情......
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: