手持裝置點選響應速度,滑鼠事件與touch事件的那些事

葉小釵發表於2013-10-19

前言

現在一直在做移動端的開發,這次將單頁應用的網頁內嵌入了app,於是老大反映了一個問題:
app應用點選響應慢!
我開始不以為然,於是拿著網頁版的試了試,好像確實有一定延遲,於是開始了研究,最後選擇了touch取代滑鼠事件

但是,touch事件取代mouse事件,還是有一定問題的,據說網上問題很多,因為兩者之間還是有一定差異
而且如果完全使用touch事件,對自動化測試的同事來說,他們的系統根本不支援touch事件,再者我們平時網頁開發也不方便
所以,瞭解滑鼠事件與touch事件的區別,探討滑鼠事件與touch事件的相容也是有必要的,於是我們開始今天的學習吧
PS:這裡使用zepto框架,懶得自己搞了......

事件差異

滑鼠事件

首先,我們來看看滑鼠事件相關吧:

 1 var startTime;
 2 var log = function (msg) {
 3     console.log(new Date().getTime() - startTime);
 4     console.log(msg);
 5 };
 6 var mouseDown = function () {
 7     startTime = new Date().getTime();
 8     log('mouseDown');
 9 };
10 var mouseClick = function () {
11     log('mouseClick');
12 };
13 var mouseUp = function () {
14     log('mouseUp');
15 };
16  
17 document.addEventListener('mousedown', mouseDown);
18 document.addEventListener('click', mouseClick);
19 document.addEventListener('mouseup', mouseUp);

從這裡看到了,滑鼠順序是有mousedown -> click -> mouseup 的順序,其時間差也出來了

touch事件

然後我們看看touch事件

沒有click

touch包含三個事件,touchstart、touchmove、touchend,並沒有click事件,所以click事件需要自己模擬,這個我們後面來看看

 1 var startTime;
 2 var log = function (msg) {
 3     console.log(new Date().getTime() - startTime);
 4     console.log(msg);
 5 };
 6 var touchStart = function () {
 7     startTime = new Date().getTime();
 8     log('touchStart');
 9 };
10 
11 var touchEnd = function () {
12     log('touchEnd');
13 };
14 
15 document.addEventListener('touchstart', touchStart);
16 document.addEventListener('touchend', touchEnd);

在chrome開啟touch事件的情況下,可以看到這個結果

混合事件

現在我們在手機上同時觸發兩者事件看看區別,這裡程式碼做一定修改

 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     <script id="others_zepto_10rc1" type="text/javascript" class="library" src="http://sandbox.runjs.cn/js/sandbox/other/zepto.min.js"></script>
 6 </head>
 7 <body>
 8     <div id="d" style="width: 100px; height: 100px; border: 1px solid black;">
 9     </div>
10 </body>
11 <script type="text/javascript">
12     var startTime;
13     var log = function (msg) {
14         var div = $('<div></div>');
15         div.html((new Date().getTime()) + ': ' + (new Date().getTime() - startTime) + ': ' + msg)
16         $('body').append(div);
17 
18     };
19     var touchStart = function () {
20         startTime = new Date().getTime();
21         log('touchStart');
22     };
23     var touchEnd = function () {
24         log('touchEnd');
25 
26     };
27     var mouseDown = function () {
28         log('mouseDown');
29     };
30     var mouseClick = function () {
31         log('mouseClick');
32     };
33     var mouseUp = function () {
34         log('mouseUp');
35 
36     };
37     var d = $('#d');
38     d.bind('mousedown', mouseDown);
39     d.bind('click', mouseClick);
40     d.bind('mouseup', mouseUp);
41     d.bind('touchstart', touchStart);
42     d.bind('touchend', touchEnd);
43 </script>
44 </html>

測試地址

http://sandbox.runjs.cn/show/ey54cgqf

此處手機與電腦有非常大的區別!!!

結論

不要同時給document繫結滑鼠與touch事件

document.addEventListener('mousedown', mouseDown);
document.addEventListener('click', mouseClick);
document.addEventListener('mouseup', mouseUp);
document.addEventListener('touchstart', touchStart);
document.addEventListener('touchend', touchEnd);

這個樣子,在手機上不會觸發click事件,click事件要繫結到具體元素

PS:此處的原因我就不去研究了,如果您知道為什麼,請留言

手機上mousedown本來響應就慢

經過測試,電腦上touch與click事件的差距不大,但是手機上,當我們手觸碰螢幕時,要過300ms左右才會觸發mousedown事件

所以click事件在手機上響應就是慢一拍

資料說明

可以看到,在手機上使用click事件其實對使用者體驗並不好,所以我們可能會逐步使用touch事件

引數差異

現在,我們來看看滑鼠與touch事件的引數差異

 1 var startTime;
 2 var log = function (msg, e) {
 3     console.log(e);
 4     var div = $('<div></div>');
 5     div.html((new Date().getTime()) + ': ' + (new Date().getTime() - startTime) + ': ' + msg)
 6     $('body').append(div);
 7 
 8 };
 9 var touchStart = function (e) {
10     startTime = new Date().getTime();
11     log('touchStart', e);
12 };
13 var touchEnd = function (e) {
14     log('touchEnd', e);
15 
16 };
17 var mouseDown = function (e) {
18     log('mouseDown', e);
19 };
20 var mouseClick = function (e) {
21     log('mouseClick', e);
22 };
23 var mouseUp = function (e) {
24     log('mouseUp', e);
25 
26 };
27 var d = $('#d');
28 d.bind('mousedown', mouseDown);
29 d.bind('click', mouseClick);
30 d.bind('mouseup', mouseUp);
31 d.bind('touchstart', touchStart);
32 d.bind('touchend', touchEnd);

事件引數(touchstart/mouseup)

我們來看幾個關鍵的地方:

changedTouches/touches/targetTouches

touches:為螢幕上所有手指的資訊

PS:因為手機螢幕支援多點觸屏,所以這裡的引數就與手機有所不同

targetTouches:手指在目標區域的手指資訊

changedTouches:最近一次觸發該事件的手指資訊

比如兩個手指同時觸發事件,2個手指都在區域內,則容量為2,如果是先後離開的的話,就會先觸發一次再觸發一次,這裡的length就是1,只統計最新的

PS:一般changedTouches的length都是1

touchend時,touches與targetTouches資訊會被刪除,changedTouches儲存的最後一次的資訊,最好用於計算手指資訊

這裡要使用哪個資料各位自己看著辦吧,我也不是十分清晰(我這裡還是使用changedTouches吧)

引數資訊(changedTouches[0])

幾個重要通用點:

① clientX:在顯示區的座標

② pageX:滑鼠在頁面上的位置

screenX:滑鼠在螢幕上的座標(我是雙屏所以x很大)

④ target:當前元素

幾個重要不同點:

layerX:這個是相對距離,這個不同,所以不要用這個東西了

② ......

這個有必要說明下,比如我們改下程式碼:

手持裝置點選響應速度,滑鼠事件與touch事件的那些事
 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      <script id="others_zepto_10rc1" type="text/javascript" class="library" src="http://sandbox.runjs.cn/js/sandbox/other/zepto.min.js"></script>
 6     
 7 </head>
 8 <body>
 9 <div style=" position: relative; width: 500px; height: 300px; border: 1px solid black;">
10 <div id="d" style=" position: absolute; top: 50px; left: 50px; width: 100px; height: 100px; border: 1px solid black;" ></div>
11 </div>
12 </body>
13 
14 <script type="text/javascript">
15 var startTime;
16 var log = function (msg, e) {
17     console.log(e);
18     var div = $('<div></div>');
19     div.html((new Date().getTime()) + ': ' + (new Date().getTime() - startTime) + ': ' + msg)
20     $('body').append(div);
21 
22 };
23 var touchStart = function (e) {
24     startTime = new Date().getTime();
25     log('touchStart', e);
26 };
27 var touchEnd = function (e) {
28     log('touchEnd', e);
29 
30 };
31 var mouseDown = function (e) {
32     log('mouseDown', e);
33 };
34 var mouseClick = function (e) {
35     log('mouseClick', e);
36 };
37 var mouseUp = function (e) {
38     log('mouseUp', e);
39 
40 };
41 var d = $('#d');
42 d.bind('mousedown', mouseDown);
43 d.bind('click', mouseClick);
44 d.bind('mouseup', mouseUp);
45 d.bind('touchstart', touchStart);
46 d.bind('touchend', touchEnd);
47 
48     </script>
49 </html>
View Code

測試地址

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

各位自己執行看看差異吧

簡單擴充套件touch事件

touch沒有click事件,於是有zepto搞了個tap事件,我們這裡先來簡單模擬一下,再看原始碼怎麼幹的

 1 var mouseData = {
 2     sTime: 0,
 3     eTime: 0,
 4     sX: 0,
 5     eX: 0,
 6     sY: 0,
 7     eY: 0
 8 };
 9 var log = function (msg) {
10     console.log(msg);
11 };
12 var touchStart = function (e) {
13     var pos = e.changedTouches[0];
14     mouseData.sTime = new Date().getTime();
15     mouseData.sX = pos.pageX;
16     mouseData.sY = pos.pageY;
17 };
18 var touchMove = function (e) {
19     //        var pos = e.changedTouches[0];
20     //        mouseData.eTime = new Date().getTime();
21     //        mouseData.eX = pos.pageX;
22     //        mouseData.eY = pos.pageY;
23     e.preventDefault();
24     return false;
25 };
26 var touchEnd = function (e) {
27     var pos = e.changedTouches[0];
28     mouseData.eTime = new Date().getTime();
29     mouseData.eX = pos.pageX;
30     mouseData.eY = pos.pageY;
31     var data = onTouchEnd();
32     log(data);
33     var d = $('body');
34     d.append($('<div>間隔:' + data.timeLag + ', 方向:' + data.dir + '</div>'));
35 };
36 var onTouchEnd = function () {
37     //時間間隔
38     var timeLag = mouseData.eTime - mouseData.sTime;
39     //移動狀態,預設亂移動
40     var dir = 'move';
41     if (mouseData.sX == mouseData.eX) {
42         if (mouseData.eY - mouseData.sY > 0) dir = 'down';
43         if (mouseData.eY - mouseData.sY < 0) dir = 'up';
44         if (mouseData.eY - mouseData.sY == 0) dir = 'tap';
45     }
46     if (mouseData.sY == mouseData.eY) {
47         if (mouseData.eX - mouseData.sX > 0) dir = 'right';
48         if (mouseData.eX - mouseData.sX < 0) dir = 'left';
49         if (mouseData.eX - mouseData.sX == 0) dir = 'tap';
50     }
51     return {
52         timeLag: timeLag,
53         dir: dir
54     };
55 };
56 
57 var touchEvents = function (el, func) {
58     el = el || document;
59     func = func || function () { };
60     el.addEventListener('touchstart', touchStart);
61     el.addEventListener('touchmove', touchMove);
62     el.addEventListener('touchend', touchEnd);
63 };
64 var d = $('body');
65 touchEvents(d[0]);

測試地址

http://sandbox.runjs.cn/show/2n9nqssv

這裡就可以看到一次touch事件是tap還是up等屬性,當然很多時候我們需要設定x方向或者y方向不可拖動,這樣就更好呈現

時間間隔長短可以讓我們判斷自己的拖動是長拖動還是短拖動,長拖動也許使用者希望動畫慢點,短拖動也許動畫就快了

touch事件程式碼彙總

  1 var log = function (msg) {
  2     console.log(msg);
  3 };
  4 var d = $('body');
  5 
  6 var touchEvents = function (el, type, func) {
  7     this.long = 400; //用於設定長點選閥值
  8     this.el = el || document;
  9     this.func = func || function () { };
 10     this.type = type || 'tap';
 11     this.mouseData = {
 12         sTime: 0,
 13         eTime: 0,
 14         sX: 0,
 15         eX: 0,
 16         sY: 0,
 17         eY: 0
 18     };
 19     this.addEvent();
 20 
 21 };
 22 touchEvents.prototype = {
 23     constructor: touchEvents,
 24     addEvent: function () {
 25         var scope = this;
 26         this.startFn = function (e) {
 27             scope.touchStart.call(scope, e);
 28         };
 29         this.moveFn = function (e) {
 30             scope.touchMove.call(scope, e);
 31         };
 32         this.endFn = function (e) {
 33             scope.touchEnd.call(scope, e);
 34         };
 35         this.el.addEventListener('touchstart', this.startFn);
 36         //此處可以換成這樣
 37         //            document.addEventListener('touchmove', this.touchMove);
 38         this.el.addEventListener('touchmove', this.moveFn);
 39         this.el.addEventListener('touchend', this.endFn);
 40     },
 41     removeEvent: function () {
 42         this.el.removeEventListener('touchstart', this.touchStart);
 43         this.el.removeEventListener('touchmove', this.touchMove);
 44         this.el.removeEventListener('touchend', this.touchEnd);
 45     },
 46     touchStart: function (e) {
 47         var pos = e.changedTouches[0];
 48         this.mouseData.sTime = new Date().getTime();
 49         this.mouseData.sX = pos.pageX;
 50         this.mouseData.sY = pos.pageY;
 51     },
 52     touchMove: function (e) {
 53         e.preventDefault();
 54         return false;
 55     },
 56     touchEnd: function (e) {
 57         var pos = e.changedTouches[0];
 58         this.mouseData.eTime = new Date().getTime();
 59         this.mouseData.eX = pos.pageX;
 60         this.mouseData.eY = pos.pageY;
 61         this.onTouchEnd();
 62     },
 63     onTouchEnd: function () {
 64         if (this.type == this._getDir()) {
 65 
 66         }
 67     },
 68     _getDir: function () {
 69         //時間間隔,間隔小於100都認為是快速,大於400的認為是慢速
 70         var timeLag = this.mouseData.eTime - this.mouseData.sTime;
 71         var dir = 'swipe';
 72         if (timeLag > this.long) dir = 'longSwipe';
 73         if (this.mouseData.sX == this.mouseData.eX && this.mouseData.sY == this.mouseData.eY) {
 74             dir = 'tap';
 75             if (timeLag > this.long) dir = 'longTap';
 76         } else {
 77             if (Math.abs(this.mouseData.eY - this.mouseData.sY) > Math.abs(this.mouseData.eX - this.mouseData.sX)) {
 78                 dir = this._getUDDir(dir);
 79             } else {
 80                 dir = 'swipe';
 81                 dir = this._getLRDir(dir);
 82             }
 83         }
 84         log(dir);
 85         d.append($('<div>間隔:' + timeLag + ', 方向:' + dir + '</div>'));
 86         return dir;
 87     },
 88     //單獨用於計算上下的
 89     _getUDDir: function (dir) {
 90         if (this.mouseData.eY - this.mouseData.sY > 0) dir += 'Down';
 91         if (this.mouseData.eY - this.mouseData.sY < 0) dir += 'Up';
 92         return dir;
 93     },
 94     //計算左右
 95     _getLRDir: function (dir) {
 96         if (this.mouseData.eX - this.mouseData.sX > 0) dir += 'Right';
 97         if (this.mouseData.eX - this.mouseData.sX < 0) dir += 'Left';
 98         return dir;
 99     }
100 };
101 
102 new touchEvents(d[0], 'swipe', function () {
103 //        d.append($('<div>間隔:' + data.timeLag + ', 方向:' + data.dir + '</div>'));
104 });

測試地址

http://sandbox.runjs.cn/show/rpohk79w

測試時請使用chrome,並且開啟touch事件

測試效果

完整可繫結事件程式碼

手持裝置點選響應速度,滑鼠事件與touch事件的那些事
  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>
View Code

這個程式碼基本可用了,但是使用上不是很方便,我們這裡就不關注了,下面我們來看看zepto的程式碼和相容問題

zepto的touch與相容

先上zepto原始碼,一看就知道我寫的有多不行啦!

手持裝置點選響應速度,滑鼠事件與touch事件的那些事
  1 (function ($) {
  2     var touch = {},
  3     touchTimeout, tapTimeout, swipeTimeout,
  4     longTapDelay = 750, longTapTimeout
  5 
  6     function parentIfText(node) {
  7         return 'tagName' in node ? node : node.parentNode
  8     }
  9 
 10     function swipeDirection(x1, x2, y1, y2) {
 11         var xDelta = Math.abs(x1 - x2), yDelta = Math.abs(y1 - y2)
 12         return xDelta >= yDelta ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down')
 13     }
 14 
 15     function longTap() {
 16         longTapTimeout = null
 17         if (touch.last) {
 18             touch.el.trigger('longTap')
 19             touch = {}
 20         }
 21     }
 22 
 23     function cancelLongTap() {
 24         if (longTapTimeout) clearTimeout(longTapTimeout)
 25         longTapTimeout = null
 26     }
 27 
 28     function cancelAll() {
 29         if (touchTimeout) clearTimeout(touchTimeout)
 30         if (tapTimeout) clearTimeout(tapTimeout)
 31         if (swipeTimeout) clearTimeout(swipeTimeout)
 32         if (longTapTimeout) clearTimeout(longTapTimeout)
 33         touchTimeout = tapTimeout = swipeTimeout = longTapTimeout = null
 34         touch = {}
 35     }
 36 
 37     $(document).ready(function () {
 38         var now, delta
 39 
 40         $(document.body)
 41       .bind('touchstart', function (e) {
 42           now = Date.now()
 43           delta = now - (touch.last || now)
 44           touch.el = $(parentIfText(e.touches[0].target))
 45           touchTimeout && clearTimeout(touchTimeout)
 46           touch.x1 = e.touches[0].pageX
 47           touch.y1 = e.touches[0].pageY
 48           if (delta > 0 && delta <= 250) touch.isDoubleTap = true
 49           touch.last = now
 50           longTapTimeout = setTimeout(longTap, longTapDelay)
 51       })
 52       .bind('touchmove', function (e) {
 53           cancelLongTap()
 54           touch.x2 = e.touches[0].pageX
 55           touch.y2 = e.touches[0].pageY
 56           if (Math.abs(touch.x1 - touch.x2) > 10)
 57               e.preventDefault()
 58       })
 59       .bind('touchend', function (e) {
 60           cancelLongTap()
 61 
 62           // swipe
 63           if ((touch.x2 && Math.abs(touch.x1 - touch.x2) > 30) ||
 64             (touch.y2 && Math.abs(touch.y1 - touch.y2) > 30))
 65 
 66               swipeTimeout = setTimeout(function () {
 67                   touch.el.trigger('swipe')
 68                   touch.el.trigger('swipe' + (swipeDirection(touch.x1, touch.x2, touch.y1, touch.y2)))
 69                   touch = {}
 70               }, 0)
 71 
 72           // normal tap
 73           else if ('last' in touch)
 74 
 75           // delay by one tick so we can cancel the 'tap' event if 'scroll' fires
 76           // ('tap' fires before 'scroll')
 77               tapTimeout = setTimeout(function () {
 78 
 79                   // trigger universal 'tap' with the option to cancelTouch()
 80                   // (cancelTouch cancels processing of single vs double taps for faster 'tap' response)
 81                   var event = $.Event('tap')
 82                   event.cancelTouch = cancelAll
 83                   touch.el.trigger(event)
 84 
 85                   // trigger double tap immediately
 86                   if (touch.isDoubleTap) {
 87                       touch.el.trigger('doubleTap')
 88                       touch = {}
 89                   }
 90 
 91                   // trigger single tap after 250ms of inactivity
 92                   else {
 93                       touchTimeout = setTimeout(function () {
 94                           touchTimeout = null
 95                           touch.el.trigger('singleTap')
 96                           touch = {}
 97                       }, 250)
 98                   }
 99 
100               }, 0)
101 
102       })
103       .bind('touchcancel', cancelAll)
104 
105         $(window).bind('scroll', cancelAll)
106     })
107 
108   ; ['swipe', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown', 'doubleTap', 'tap', 'singleTap', 'longTap'].forEach(function (m) {
109       $.fn[m] = function (callback) { return this.bind(m, callback) }
110   })
111 })(Zepto)
View Code

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   })

我就幹了這麼一點點事情......

待續

今天耗時過長,暫時到這裡,對滑鼠等操作,對event引數的相容我們後面點再看看

相關文章