移動web開發(fā)之touch事件實例詳解
前面的話
iOS版Safari為了向開發(fā)人員傳達一些特殊信息,新增了一些專有事件。因為iOS設(shè)備既沒有鼠標也沒有鍵盤,所以在為移動Safari開發(fā)交互性網(wǎng)頁時,常規(guī)的鼠標和鍵盤事件根本不夠用。隨著Android 中的WebKit的加入,很多這樣的專有事件變成了事實標準,導致W3C開始制定Touch Events規(guī)范。本文將詳細介紹移動端touch事件
概述
包含iOS 2.0軟件的iPhone 3G發(fā)布時,也包含了一個新版本的Safari瀏覽器。這款新的移動Safari提供了一些與觸摸(touch)操作相關(guān)的新事件。后來,Android上的瀏覽器也實現(xiàn)了相同的事件。觸摸事件會在用戶手指放在屏幕上面時、在屏幕上滑動時或從屏幕上移開時觸發(fā)。具體來說,有以下幾個觸摸事件
touchstart:當手指觸摸屏幕時觸發(fā);即使已經(jīng)有一個手指放在了屏幕上也會觸發(fā) touchmove:當手指在屏幕上滑動時連續(xù)地觸發(fā)。在這個事件發(fā)生期間,調(diào)用preventDefault()可以阻止?jié)L動 touchend:當手指從屏幕上移開時觸發(fā) touchcancel:當系統(tǒng)停止跟蹤觸摸時觸發(fā)(不常用)。關(guān)于此事件的確切觸發(fā)時間,文檔中沒有明確說明
【touchenter 和 touchleave】
觸摸事件規(guī)范中曾經(jīng)包含touchenter和touchleave事件,這兩個事件在用戶手指移入或移出某個元素時觸發(fā)。但是這兩個事件從來沒有被實現(xiàn)。微軟有這兩個事件的替代事件,但是只有IE瀏覽器支持。某些情況下可以知道用戶手指滑入滑出某個元素是素是非常有用的,所以希望這兩個事件可以重返規(guī)范
在觸摸事件中,常用的是touchstart、touchumove和touchend這三個事件,與鼠標事件的對應如下
鼠標 觸摸 mousedown touchstart mousemove touchmove mouseup touchend
[注意]touch事件在chrome模擬器下部分版本使用DOM0級事件處理程序的方式來添加事件無效
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
#test{height:200px;width:200px;background:lightblue;}
</style>
</head>
<body>
<div id="test"></div>
<script>
(function(){
var
stateMap = {
touchstart_index : 0,
touchmove_index : 0,
touchend_index : 0
},
elesMap = {
touch_obj: document.getElementById('test')
},
showIndex, handleTouch;
showIndex = function ( type ) {
elesMap.touch_obj.innerHTML = type + ':' + (++stateMap[type + '_index']);
};
handleTouch = function ( event ) {
showIndex( event.type );
};
elesMap.touch_obj.addEventListener('touchstart', function(event){handleTouch(event);});
elesMap.touch_obj.addEventListener('touchmove', function(event){handleTouch(event);});
elesMap.touch_obj.addEventListener('touchend', function(event){handleTouch(event);});
})();
</script>
</body>
</html>
300ms
300ms問題是指在某個元素執(zhí)行它的功能和執(zhí)行touch事件之間有一個300毫秒的間隔。鼠標事件、焦點事件、瀏覽器默認行為等相較于touch事件,都存在著300ms的延遲
【點透】
因為300ms的存在,會造成常見的點透問題。先來看例子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
#test {position: absolute;top: 0;left: 0;opacity: 0.5;height: 200px;width: 200px;background: lightblue;}
</style>
</head>
<body>
<a >百度</a>
<div id="test"></div>
<script>
(function () {
var
elesMap = {
touchObj: document.getElementById('test')
},
fnHide, onTouch;
fnHide = function (type) {
elesMap.touchObj.style.display = 'none';
};
onTouch = function (event) {
fnHide();
};
elesMap.touchObj.addEventListener('touchstart', function(event){onTouch(event);});
})();
</script>
</body>
</html>
淺藍色的半透明div被點擊(觸發(fā)touch事件)后,如果點擊位置正好位于鏈接的上方,則會觸發(fā)鏈接跳轉(zhuǎn)的默認行為。詳細解釋是,點擊頁面后,瀏覽器會記錄所點擊的頁面坐標,300ms后,在該坐標找到元素。在該元素上觸發(fā)點擊行為。因此,如果300ms內(nèi)同一頁面坐標的上層元素消失后,300ms后在下層元素上觸發(fā)點擊行為。這就造成了點透問題
造成這個問題,是因為觸摸屏幕的行為被重載(overload)了。在手指觸摸屏幕的瞬間,瀏覽器無法預知用戶是在輕觸(Tap)、雙觸(Double-Tap)、滑動(Swipe)、按住不放(Hold)還是其他什么操作。唯一保險的做法就是等上一會兒看接下來會發(fā)生什么
問題是在于雙觸(Double-Tap)。即便是瀏覽器檢測出手指離開了屏幕,它仍然無法判斷接下來做什么。因為瀏覽器無法知道手指是會再次回到屏幕,還是就此結(jié)束觸發(fā)輕觸事件以及事件級聯(lián)。為了確定這一點,瀏覽器不得不等待一小段時間。瀏覽器開發(fā)者找到一個最佳時間間隔,就是300毫秒
【解決辦法】
1、在touch事件的事件處理程序中增加300ms的延遲
(function () {
var
elesMap = {
touchObj: document.getElementById('test')
},
fnHide, onTouch;
fnHide = function (type) {
elesMap.touchObj.style.display = 'none';
};
onTouch = function (event) {
setTimeout(function(){
fnHide();
},300);
};
elesMap.touchObj.addEventListener('touchstart', function (event) { onTouch(event); });
})();
2、使用緩動動畫,增加300ms的過渡效果,注意display屬性無法使用transition
3、加入中間層的dom元素,讓中間層接受這個穿透事件,稍后隱藏
4、上下兩級都使用tap事件,但默認行為不可避免
5、在document上的touchstart事件,阻止默認行為。
document.addEventListener('touchstart',function(e){
e.preventDefault();
})
接著,添加a標簽的跳轉(zhuǎn)行為
a.addEventListener('touchstart',function(){
window.location.;
})
但是,這種方法有副作用,會造成頁面無法滾動、文本無法選中等。如果在某個元素上,需要恢復文本選中的行為,則可以使用阻止冒泡來恢復
el.addEventListener('touchstart',function(e){
e.stopPropagation();
})
事件對象
【基礎(chǔ)信息】
每個觸摸事件的event對象都提供了在鼠標事件中常見的屬性,包括事件類型、事件目標對象、事件冒泡、事件流、默認行為等
以touchstart為例,示例代碼如下
<script>
(function () {
var
elesMap = {
touchObj: document.getElementById('test')
},
onTouch;
onTouch = function (e) {
console.log(e)
};
elesMap.touchObj.addEventListener('touchstart', function (event) { onTouch(event); });
})();
</script>
1、currentTarget屬性返回事件正在執(zhí)行的監(jiān)聽函數(shù)所綁定的節(jié)點
2、target屬性返回事件的實際目標節(jié)點
3、srcElement屬性與target屬性功能一致
//當前目標 currentTarget:[object HTMLDivElement] //實際目標 target:[object HTMLDivElement] //實際目標 srcElement:[object HTMLDivElement]
4、eventPhase屬性返回一個整數(shù)值,表示事件目前所處的事件流階段。0表示事件沒有發(fā)生,1表示捕獲階段,2表示目標階段,3表示冒泡階段
5、bubbles屬性返回一個布爾值,表示當前事件是否會冒泡。該屬性為只讀屬性
6、cancelable屬性返回一個布爾值,表示事件是否可以取消。該屬性為只讀屬性
//事件流 eventPhase: 2 //可冒泡 bubbles: true //默認事件可取消 cancelable: true
【touchList】
除了常見的DOM屬性外,觸摸事件對象有一個touchList數(shù)組屬性,其中包含了每個觸摸點的信息。如果用戶使用四個手指觸摸屏幕,這個數(shù)組就會有四個元素。一共有三個這樣的數(shù)組
1、touches:當前觸摸屏幕的觸摸點數(shù)組(至少有一個觸摸在事件目標元素上)
2、changedTouches :導致觸摸事件被觸發(fā)的觸摸點數(shù)組
3、targetTouches:事件目標元素上的觸摸點數(shù)組
如果用戶最后一個手指離開屏幕觸發(fā)touchend事件,這最后一個觸摸點信息不會出現(xiàn)在targetTouches和touches數(shù)組中,但是會出現(xiàn)在changedTouched數(shù)組中。因為是它的離開觸發(fā)了touchend事件,所以changedTouches數(shù)組中仍然包含它。上面三個數(shù)組中,最常用的是changedTouches數(shù)組
(function () {
var
elesMap = {
touchObj: document.getElementById('test')
},
onTouch;
onTouch = function (e) {
elesMap.touchObj.innerHTML = 'touches:' + e.touches.length
+ '<br>changedTouches:' + e.changedTouches.length
+ '<br>targetTouches:' + e.targetTouches.length;
};
elesMap.touchObj.addEventListener('touchstart', function (event) { onTouch(event); });
})();
【事件坐標】
上面這些觸摸點數(shù)組中的元素可以像普通數(shù)組那樣用數(shù)字索引。數(shù)組中的元素包含了觸摸點的有用信息,尤其是坐標信息。每個Touch對象包含下列屬性
clientx:觸摸目標在視口中的x坐標 clientY:觸摸目標在視口中的y坐標 identifier:標識觸摸的唯一ID pageX:觸摸目標在頁面中的x坐標(包含滾動) pageY:觸摸目標在頁面中的y坐標(包含滾動) screenX:觸摸目標在屏幕中的x坐標 screenY:觸摸目標在屏幕中的y坐標 target:觸摸的DOM節(jié)點目標
changedTouches數(shù)組中的第一個元素就是導致事件觸發(fā)的那個觸摸點對象(通常這個觸摸點數(shù)組不包含其他對象)。這個觸摸點對象含有clientX/Y和pageX/Y坐標信息。除此之外還有screenX/Y和x/y,這些坐標在瀏覽器間不太一致,不建議使用
clientX/Y和pageX/Y的區(qū)別在于前者相對于視覺視口的左上角,后者相對于布局視口的左上角。布局視口是可以滾動的
(function () {
var
elesMap = {
touchObj: document.getElementById('test')
},
onTouch;
onTouch = function (e) {
var touch = e.changedTouches[0];
elesMap.touchObj.innerHTML = 'clientX:' + touch.clientX + '<br>clientY:' + touch.clientY
+ '<br>pageX:' + touch.pageX + '<br>pageY:' + touch.pageY
+ '<br>screenX:' + touch.screenX + '<br>screenY:' + touch.screenY
};
elesMap.touchObj.addEventListener('touchstart', function (event) { onTouch(event); });
})();
以上這篇移動web開發(fā)之touch事件實例詳解就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
JS中動態(tài)創(chuàng)建元素的三種方法總結(jié)(推薦)
下面小編就為大家?guī)硪黄狫S中動態(tài)創(chuàng)建元素的三種方法總結(jié)(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-10-10
js監(jiān)聽鼠標點擊和鍵盤點擊事件并自動跳轉(zhuǎn)頁面
這篇文章主要介紹了js監(jiān)聽鼠標點擊(onmousedown)和鍵盤點擊(onkeydown)事件并自動跳轉(zhuǎn)頁面,很簡單的一個實現(xiàn)2014-09-09
Javascript函數(shù)緩存的實現(xiàn)及應用場景
Javascript函數(shù)緩存是一種提高網(wǎng)頁性能的重要技術(shù),通過將函數(shù)結(jié)果存儲在緩存中,避免重復計算,從而提高頁面加載速度和響應速度,本文主要介紹了Javascript函數(shù)緩存的實現(xiàn)及應用場景,具有一定的參考價值,感興趣的可以了解一下2023-12-12
小程序開發(fā)調(diào)用微信支付以及微信回調(diào)地址配置
本文主要介紹了小程序開發(fā)調(diào)用微信支付以及微信回調(diào)地址配置,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-05-05

