隨着智能手機和平板電腦的普及, 愈來愈多的人用移動設備瀏覽網頁,咱們平時在pc瀏覽器上用的鼠標事件,好比:click, mouseover等, 已經沒法知足移動設備觸摸屏的特色,觸摸時代的到來,離不開那些觸摸事件。javascript
TouchEventcss
表明當觸摸行爲在平面上變化的時候發生的事件.html
Touchjava
表明用戶手指與觸摸平面間的一個接觸點.git
TouchListgithub
表明一系列的Touch; 通常在用戶多個手指同時接觸觸控平面時使用這個接口.web
DocumentTouch數組
包含了一些建立 Touch對象與TouchList對象的便捷方法.瀏覽器
(參考於 https://developer.mozilla.org/zh-CN/docs/Web/API/Touch_events )dom
TouchEvent接口能夠響應基本觸摸事件(如單個手指點擊),它包含了一些具體的事件,
事件類型:
touchstart : 觸摸開始(手指放在觸摸屏上)
touchmove : 拖動(手指在觸摸屏上移動)
touchend : 觸摸結束(手指從觸摸屏上移開)
touchenter :移動的手指進入一個dom元素。
touchleave :移動的手指離開一個dom元素。
還有一個touchcancel,是在拖動中斷時候觸發。
事件屬性:
altKey : 該屬性返回一個布爾值,表示在指定的事件發生時,Alt 鍵是否處於按下狀態, event.altKey=true|false|1|0
type : 觸摸時觸發的事件類型,好比touchstart
每一個觸摸事件都包括了三個觸摸屬性列表:
1. touches:當前位於屏幕上的全部手指觸摸點的一個列表。
2. targetTouches:當前元素對象上全部觸摸點的列表。
3. changedTouches:涉及當前事件的觸摸點的列表。
它們都是一個數組,每一個元素表明一個觸摸點。
每一個觸摸點對應的Touch都有三對重要的屬性,clientX/clientY、pageX/pageY、screenX/screenY。
其中screenX/screenY表明事件發生的位置對於屏幕的偏移量,clientX/clienYt和pageX/pageY都表明事件發生位置對應對象的偏移量,不過區別是clientX/clientY不包括對象滾動而隱藏的偏移量,而pageX/pageY包括對象滾動而隱藏的偏移量。移開屏幕的那個觸摸點,只會包含在changedTouches列表中,而不會包含在touches 和targetTouches 列表中, 因此changedTouches在項目當中會比較經常使用。
示例:
<body onload="start();">
<style type="text/css"> #dom { width:500px; height:500px; background:black; } </style>
<div id="dom"></div>
<script type="text/javascript"> function onTouchStart(e){ console.log(e); } function start(){ var dom = document.getElementById('dom'); dom.addEventListener('touchstart', onTouchStart, false); } </script>
</body>
控制檯輸出以下:
觸摸事件跟鼠標事件的觸發前後順序:
Touchstart > toucheend > mousemove > mousedown > mouseup > click
不少狀況下觸摸事件跟鼠標事件會同時觸發(目的是爲了讓沒有對觸摸設備優化的代碼仍然能夠在觸摸設備上正常工做),若是使用了觸摸事件,能夠調用event.preventDefault()來阻止鼠標事件被觸發。而手指在屏幕上移動touchmove則不會觸發鼠標事件和單擊事件,在touchmove事件中加入preventDefault, 能夠禁止瀏覽器滾動屏幕,也不會影響單擊事件的觸發。
以上事件,都系統內置的,能夠直接使用,經過這些內置事件,能夠組合成不少非原生的多點觸摸手勢touch手勢。
Hammer.js是一個輕量級的JavaScript庫, 能讓你的網站輕鬆實現觸控事件, 它依賴於jQuery,用來控制觸摸設備上的多點觸控特性。
官網: http://hammerjs.github.io/
多點觸摸的實現,想了解更多能夠參考: http://www.cnblogs.com/iamlilinfeng/p/4239957.htm
zepto是輕量級兼容juqery的庫,適用於移動端開發, 具體使用方法,可參看官網, http://zeptojs.com/
zepto touch 是用於單點手勢觸發的一個touch事件模塊。
Touch.js 下載地址: https://github.com/madrobby/zepto/blob/master/src/touch.js
先看zepto的touch模塊實現:
$(document) .on('touchstart ...',function(e){ ... ... now = Date.now() delta = now - (touch.last || now) if (delta > 0 && delta <= 250) touch.isDoubleTap = true touch.last = now }) .on('touchmove ...', function(e){ }) .on('touchend ...', function(e){ ... if (deltaX < 30 && deltaY < 30) { var event = $.Event('tap') touch.el.trigger(event) } })
touch 模塊綁定事件 touchstart, touchmove, touchend 到 document上,而後經過計算事件觸發的時間差,位置差來實現自定義的tap,swipe事件。
手機上也有click事件,從觸摸到響應click事件,有會300的毫秒的延遲,緣由在於:
"Apple 準備發佈iphone的時候,爲了解決手機上web頁面過小的問題,增長了雙擊屏幕放大的功能,(double tap to zoom ),當用戶觸摸屏幕的時候,瀏覽器不知道用戶是要double tap仍是要click,因此瀏覽器在第一次tap事件後會等300ms來判斷究竟是double tap仍是click ,若是在300ms之內點擊的話,會覺得是double tap,反之是click。"
去掉click事件 300ms 的方法:
(1) 在meta裏,加 user-scalable=no 能夠阻止雙擊放大,(缺點: 部分瀏覽器支持)
(2) 使用fastclick.js 它利用多touchstart touchmove 等原生事件的封裝,來實現手機上的各類手勢,好比tap, swipe 等,
下載地址 https://github.com/ftlabs/fastclick
調用很簡單:
$(function() {
FastClick.attach(document.body);
});
缺點: 文件量有點大,爲了解決一小延遲的問題,有點得不償失。
自定義事件
// 建立事件對象
var obj = new Event('sina'); var elem = document.getElementById('dom'); //監聽sina事件 elem.addEventListener('sina', function(e){ console.log(e); },false); //分發sina事件 elem.dispatchEvent(obj);
另一個建立事件對象的方法是經過CustomEvent,相比於Event的好處是,它能夠給處理事件的函數,自定義detail值,這在實際開發中,可能會常常用到。
// 建立事件對象
var obj = new window.CustomEvent('sina', { detail: {'name': 'lily'} }); var elem = document.getElementById('dom'); //監聽sina事件 elem.addEventListener('sina', function(e){ // 能夠接收到建立事件時,傳入的detail值。 console.log(e. detail); // {'name': 'lily'} },false); //分發sina事件 elem.dispatchEvent(obj);
建立自定義事件,一個兼容性較好的函數:
zepto tap 「點透」問題
Zepto 的tap事件是經過document綁定了touchstart和touchend事件實現,若是綁定tap方法的dom元素在tap方法觸發後會隱藏、而「隱藏後,它底下同一位置正好有一個dom元素綁定了click的事件, 而clic事件有300ms延遲,觸發click事件。則會出現「點透」現象。
解決方案:
1 fastclick.js
它的實際原理是在目標元素上綁定touchstart ,touchend事件,而後在touchend這個庫直接在touchend的時候就觸發了dom上的click事件而替換了原本的觸發時間,touch事件是綁定到了具體dom而不是document上,因此e.preventDefault是有效的,能夠阻止冒泡,也能夠阻止瀏覽器默認事件。
http://www.cnblogs.com/yexiaochai/p/3442220.html
二、利用fastclick的事件原理, 直接寫一段, 採用 e.preventDefault(); 阻止「默認行爲」,將事件綁定到dom元素上,缺點在於不能使用事件代理。
elem.addEventListener(touchend, function(e){ e.preventDefault()
},false);
3. 在事件捕獲階段,若是時間差,位置差,均小於指定的值,就阻止冒泡和默認click事件的觸發。
4. 用戶點擊的時候「彈出」一個頂層DIV,屏蔽掉全部事件傳遞,而後定時自動隱藏, 這個方法比較巧妙。
參考:
tap 模塊
https://github.com/alexgibson/tap.js
ghost click
http://ariatemplates.com/blog/2014/05/ghost-clicks-in-mobile-browsers/
JavaScript和事件
http://f2e.im/t/850
備註:文章系原創和技術資料的心得總結,歡迎交流,多提寶貴意見。