下面我就為大家分享一篇行動web開發之touch事件實例詳解,具有很好的參考價值,希望對大家有幫助。
前面的話
iOS版Safari為了向開發人員傳達一些特殊訊息,新增了一些專有事件。因為iOS設備既沒有滑鼠也沒有鍵盤,所以在為行動Safari開發互動性網頁時,常規的滑鼠和鍵盤事件根本不夠用。隨著Android 中的WebKit的加入,許多這樣的專有事件變成了事實標準,導致W3C開始製定Touch Events規範。本文將詳細介紹行動端touch事件
概述
包含iOS 2.0軟體的iPhone 3G發佈時,也包含了一個新版本的Safari瀏覽器。這款新的行動Safari提供了一些與觸控(touch)操作相關的新事件。後來,Android上的瀏覽器也實作了相同的事件。觸控事件會在使用者手指放在螢幕上方時、在螢幕上滑動時或從螢幕上移開時觸發。具體來說,有以下幾個觸控事件
touchstart:当手指触摸屏幕时触发;即使已经有一个手指放在了屏幕上也会触发 touchmove:当手指在屏幕上滑动时连续地触发。在这个事件发生期间,调用preventDefault()可以阻止滚动 touchend:当手指从屏幕上移开时触发 touchcancel:当系统停止跟踪触摸时触发(不常用)。关于此事件的确切触发时间,文档中没有明确说明
【touchenter 和touchleave】
#觸控事件規範中曾經包含touchenter和touchleave事件,這兩個事件在使用者手指移入或移出某個元素時觸發。但是這兩個事件從來沒有實現。微軟有這兩個事件的替代事件,但只有IE瀏覽器支援。某些情況下可以知道使用者手指滑入滑出某個元素是素是非常有用的,所以希望這兩個事件可以重返規範
在觸控事件中,常用的是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> <p id="test"></p> <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問題是指在某個元素執行它的功能和執行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 href="https://baidu.com">百度</a> <p id="test"></p> <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>
淺藍色的半透明p被點擊(觸發touch事件)後,如果點擊位置剛好位於連結的上方,則會觸發連結跳轉的預設行為。詳細解釋是,點擊頁面後,瀏覽器會記錄所點擊的頁面座標,300ms後,在該座標找到元素。在該元素上觸發點擊行為。因此,如果300ms內同一頁面座標的上層元素消失後,300ms後在下層元素上觸發點擊行為。這就造成了點透問題
造成這個問題,是因為觸摸螢幕的行為被重載(overload)了。在手指觸摸螢幕的瞬間,瀏覽器無法預知使用者是在輕觸(Tap)、雙觸(Double-Tap)、滑動(Swipe)、按住不放(Hold)還是其他什麼操作。唯一保險的做法就是等上一會兒看接下來會發生什麼
問題是在於雙觸(Double-Tap)。即便是瀏覽器偵測出手指離開了螢幕,它仍然無法判斷接下來要做什麼。因為瀏覽器無法知道手指會再次回到螢幕,還是就此結束觸發輕觸事件以及事件級聯。為了確定這一點,瀏覽器不得不等待一小段時間。瀏覽器開發者找到一個最佳時間間隔,就是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標籤的跳轉行為
a.addEventListener('touchstart',function(){ window.location.href = 'https://cnblogs.com'; })
但是,這種方法有副作用,會造成頁面無法捲動、文字無法選取等。如果在某個元素上,需要恢復文字選取的行為,則可以使用阻止冒泡來恢復
el.addEventListener('touchstart',function(e){ e.stopPropagation(); })
#事件物件
【基礎資訊】
每個觸控事件的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屬性傳回事件正在執行的監聽函數所綁定的節點
2、target屬性傳回事件的實際目標節點
3、srcElement屬性與target屬性功能一致
//当前目标 currentTarget:[object HTMLpElement] //实际目标 target:[object HTMLpElement] //实际目标 srcElement:[object HTMLpElement]
4、eventPhase屬性傳回一個整數值,表示事件目前所處的事件流階段。 0表示事件沒有發生,1表示捕獲階段,2表示目標階段,3表示冒泡階段
5、bubbles屬性傳回一個布林值,表示目前事件是否會冒泡。此屬性為唯讀屬性
6、cancelable屬性傳回一個布林值,表示事件是否可以取消。此屬性為唯讀屬性
//事件流 eventPhase: 2 //可冒泡 bubbles: true //默认事件可取消 cancelable: true
【touchList】
除了常见的DOM属性外,触摸事件对象有一个touchList数组属性,其中包含了每个触摸点的信息。如果用户使用四个手指触摸屏幕,这个数组就会有四个元素。一共有三个这样的数组
1、touches:当前触摸屏幕的触摸点数组(至少有一个触摸在事件目标元素上)
2、changedTouches :导致触摸事件被触发的触摸点数组
3、targetTouches:事件目标元素上的触摸点数组
如果用户最后一个手指离开屏幕触发touchend事件,这最后一个触摸点信息不会出现在targetTouches和touches数组中,但是会出现在changedTouched数组中。因为是它的离开触发了touchend事件,所以changedTouches数组中仍然包含它。上面三个数组中,最常用的是changedTouches数组
(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); }); })();
【事件坐标】
上面这些触摸点数组中的元素可以像普通数组那样用数字索引。数组中的元素包含了触摸点的有用信息,尤其是坐标信息。每个Touch对象包含下列属性
clientx:触摸目标在视口中的x坐标 clientY:触摸目标在视口中的y坐标 identifier:标识触摸的唯一ID pageX:触摸目标在页面中的x坐标(包含滚动) pageY:触摸目标在页面中的y坐标(包含滚动) screenX:触摸目标在屏幕中的x坐标 screenY:触摸目标在屏幕中的y坐标 target:触摸的DOM节点目标
changedTouches数组中的第一个元素就是导致事件触发的那个触摸点对象(通常这个触摸点数组不包含其他对象)。这个触摸点对象含有clientX/Y和pageX/Y坐标信息。除此之外还有screenX/Y和x/y,这些坐标在浏览器间不太一致,不建议使用
clientX/Y和pageX/Y的区别在于前者相对于视觉视口的左上角,后者相对于布局视口的左上角。布局视口是可以滚动的
(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); }); })();
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
在angularjs中使用$http实现异步上传Excel文件方法
以上是行動web開發中有關touch事件(詳細教學)的詳細內容。更多資訊請關注PHP中文網其他相關文章!