移動端觸摸(touch)事件

來源:互聯網
上載者:User

標籤:無法   不必要   1.5   文章   ini   end   NPU   代碼   分享   

移動端時代已經到來,作為前端開發的我們沒有理由也不應該坐井觀天,而是勇敢地跳出心裡的那口井,去擁抱蔚藍的天空。該來的總會來,我們要做的就是接受未知的挑戰。正如你所看到的,這是一篇關於移動端觸摸事件的文章,也就是我們平時在手機中用得最多的動作:touch。現在讓我們開始 touch touch touch 吧!

Touch 事件

首先 touch 包含三類事件,它們分別是:touchstart、touchmove、touchend 。望文生義這種本能相信你應該會有,但在這裡我還是有必需對這三個詞進行一翻不必要的解釋。

授課時間

touchstart:手指觸摸到一個 DOM 元素時觸發。

 

touchmove:手指在一個 DOM 元素上滑動時觸發。

 

touchend:手指從一個 DOM 元素上移開時觸發。

這三個事件又分別對應三個相同的觸摸列表:

授課時間

touches:正在觸控螢幕幕的所有手指的一個列表。

 

targetTouches:正在觸摸當前 DOM 元素上的手指的一個列表。

 

changedTouches:涉及當前事件的手指的一個列表。

Touch 屬性

事件對應的三個列表雖然名字不一樣,但是它們裡面裝的東西都是差不多的,包含了當前事件的一些相關資訊,比如:一些座標資訊。

TouchList {0: Touch, length: 1}length:10:Touch    clientX:65 // 觸摸點在瀏覽器視窗中的橫座標    clientY:18 // 觸摸點在瀏覽器視窗中的縱座標    force:1 // 觸摸點壓力大小    identifier:0 // 觸摸點唯一標識(ID)    pageX:65 // 觸摸點在頁面中的橫座標    pageY:18 // 觸摸點在頁面中的縱座標    radiusX:11.5 // 觸摸點橢圓的水平半徑    radiusY:11.5 // 觸摸點橢圓的垂直半徑    rotationAngle:0 // 旋轉角度    screenX:560 // 觸摸點在螢幕中的橫座標    screenY:175 // 觸摸點在螢幕中的縱座標target:div#touchLog 觸摸目標__proto__:Touch__proto__:TouchList

上面就是一個 TouchList 列表。它對應的就是前面提到的三種事件(touchstart、touchmove、touchend)中的一種,在觸發時產生的一個對象列表。列表裡最有用的就是 Touch 對象了,Touch 對象裡存放著對應事件的一些相關的資訊,我們就是通過這種個事件裡這些屬性的有機結合來實現各種效果。

通過上面的 radiusX,radiusY,rotationAngle 這三個屬性就可以計算出你的手指觸摸手機螢幕時的一個接觸面,只不過這個接觸面是用一個近似的橢圓來表示,也就是說它不是一個真正意義上的接觸面,而是一個大概的接觸面。相信心細的朋友應該會看到 TouchList 對象裡有一個 length 屬性,並且它的值為 1  ,這說明當前只有一個手指觸發了事件(比如:touchstart 事件),換句話說,此時你只有一個手指放到了手機螢幕上,這個手指對應的一些資訊存放在 Touch 對象裡。因為只有一個手指放在了螢幕上,所以這個 TouchList 裡只有一個 Touch 對象,並且是第一個下標為 0 。TouchList 列表裡還有一個 target 屬性,這個應該很好理解,就是觸摸的目標。

為了讓你能更加立體地理解上面的這些屬性,我專門從網上找了一段話來作為補充:

來自 mozilla

1.Touch.identifier:此 Touch 對象的唯一識別碼。 一次觸摸動作(我們指的是手指的觸摸)在平面上移動的整個過程中,該標識符不變。 可以根據它來判斷跟蹤的是否是同一次觸摸過程,此值為唯讀屬性。

 

2.Touch.screenX:觸點相對於螢幕左邊沿的X座標。唯讀屬性。

 

3.Touch.screenY:觸點相對於螢幕上邊沿的Y座標。唯讀屬性。

 

4.Touch.clientX:觸點相對於可見視區(visual viewport)左邊沿的X座標。不包括任何滾動位移。唯讀屬性。

 

5.Touch.clientY:觸點相對於可見視區(visual viewport)上邊沿的Y座標。不包括任何滾動位移。唯讀屬性。

 

6.Touch.pageX:觸點相對於HTML文檔左邊沿的X座標。當存在水平滾動的位移時,這個值包含了水平滾動的位移。唯讀屬性。

 

7.Touch.pageY:觸點相對於HTML文檔上邊沿的Y座標。當存在水平滾動的位移時,這個值包含了垂直滾動的位移。唯讀屬性。

 

8.Touch.radiusX:能夠包圍使用者和觸摸平面的接觸面的最小橢圓的水平軸(X軸)半徑。這個值的單位和 screenX 相同。唯讀屬性。

 

9.Touch.radiusY:能夠包圍使用者和觸摸平面的接觸面的最小橢圓的垂直軸(Y軸)半徑。這個值的單位和 screenY 相同。唯讀屬性。

 

10.Touch.rotationAngle:它是這樣一個角度值:由radiusX 和 radiusY描述的正方向的橢圓,需要通過順時針旋轉這個角度值,才能最精確地覆蓋住使用者和觸摸平面的接觸面。唯讀屬性。

 

11.Touch.force:手指擠壓觸摸平面的壓力大小,從0.0(沒有壓力)到1.0(最大壓力)的浮點數。唯讀屬性。

 

12.Touch.target:當這個觸點最開始被跟蹤時(在 touchstart 事件中),觸點位於的HTML元素。哪怕在觸點移動過程中,觸點的位置已經離開了這個元素的有效互動地區,或者這個元素已經被從文檔中移除。需要注意的是,如果這個元素在觸摸過程中被移除,這個事件仍然會指向它,但是不會再冒泡這個事件到 window 或 document 對象。因此,如果有元素在觸摸過程中可能被移除,最佳實務是將觸摸事件的監聽器綁定到這個元素本身,防止元素被移除後,無法再從它的上一級元素上偵測到從該元素冒泡的事件。唯讀屬性。

Touch 初探單指操作

為了更深入地理解 Touch 事件,我們現在來做一個簡單的 DEMO 。

HTML 程式碼

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>移動端觸摸(touch)事件</title>    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />    <style>        #touchLog {            padding: 12px;            width: 100%;            box-sizing: border-box;            height: 300px;        }    </style></head><body>    <div id="touchLog">這裡顯示 touch 資訊</div></body></html>

JavaScript 代碼

<script>var obj = document.getElementById("touchLog");obj.addEventListener("touchstart", showMsg);function showMsg(ev) {    console.log(ev.touches);    console.log(ev.targetTouches);    console.log(ev.changedTouches);}</script>

上面綁定的是 touchstart 事件,其它兩個事件的用法一樣,只是觸發的時間點不一樣而已。運行上面的代碼會輸出如的結果:

可能你會問:為什麼它們的資料都是一樣的,其實也很好理解,當你按下螢幕觸發 touchstart 此時,然後執行了showMsg() 方法。那改成 touchmove 呢?不出意外的話,當你移動手指時第一組中的這三個 TouchList 也是一樣的,為什麼說第一組呢,因為 touchmove 是在你移動手指時才會觸發的,所以當你不斷移動手指時會多次觸發自然而然地就會出現多組資料。但對於 touchend 就有點不一樣了。你可以運行如下代碼查看 touchend 與其它兩個的區別:

<script>var touchLog = document.getElementById("touchLog");touchLog.addEventListener("touchstart", showMsgTouchstart);function showMsgTouchstart(ev) {    console.log("---touchstart---");    console.log(ev.touches);    console.log(ev.targetTouches);    console.log(ev.changedTouches);}touchLog.addEventListener("touchmove", showMsgTouchmove);function showMsgTouchmove(ev) {    console.log("---touchmove---");    console.log(ev.touches);    console.log(ev.targetTouches);    console.log(ev.changedTouches);}touchLog.addEventListener("touchend", showMsgTouchend);function showMsgTouchend(ev) {    console.log("---touchend---");    console.log(ev.touches);    console.log(ev.targetTouches);    console.log(ev.changedTouches);}</script>

運行後你會發現 touchend 的 touches、targetTouches 裡是沒有 touch 對象的,length 值都為零,如:

這裡我們還可以做別一個更有意思的測試,那就是觸摸目標元素後,手指再滑出目標元素。上面三個事件對應的 touches、targetTouches 和 changedTouches 又會輸出什麼呢?還會是一樣?

如果不出意外

1.touchstart 事件:touches、targetTouches 和 changedTouches 是一樣的。

 

2.touchmove 事件:touches、targetTouches 和 changedTouches 是一樣的(資料依然會有多組,原因上面也已經分析過了)。

 

3.touchend 事件:當你手指離開螢幕後,也就是 touchend 事件觸發時,touches、targetTouches 的 TouchList 的 length 同樣為0,也就是說沒有 touch 對象。

所以使用 touchend 事件時需要注意只有 changedTouches 會存有觸摸對象。但在 TouchList 對象中的 target 屬性的值都為 div#touchLog,也就是說不管你觸控螢幕幕後手指是在目標元素上還是滑出目標元素,這個 target 屬性的值還是 div#touchLog 。只要觸摸了螢幕 force 的值都是 1 ,所以在這裡感覺這個 force 還沒有什麼用武之地。

多指操作

我們先來看看下面的這一段代碼,並且如果條件允許的話請用手機訪問:http://yunkus.com/demo/mobile-touch-event/multi-finger-touchstart.html 查看touchstart 事件觸發時的效果,代碼如下:

<script>var obj = document.getElementById("touchLog");obj.addEventListener("touchstart", showMsg);function showMsg(ev) {        obj.innerHTML = "";        var touchesStr = "";        var targetTouchesStr = "";        for (var i = 0; i < ev.touches.length; i++) {            touchesStr += "identifier:" + ev.touches[i].identifier + ",x 軸座標:" + ev.touches[i].clientX + "<br>";            targetTouchesStr += "identifier:" + ev.targetTouches[i].identifier + ",x 軸座標:" + ev.targetTouches[i]                .clientX + "<br>";        }        obj.innerHTML = "下面是 ev.touches 資料:<br>" + touchesStr +            "<br>下面是 ev.targetTouches 資料:<br>" + targetTouchesStr +            "<br>下面是 ev.changedTouches 資料:<br>" +            "identifier:" + ev.changedTouches[0].identifier + ",x 軸座標:" + ev.changedTouches[0].clientX + "<br>";}</script>

訪問 http://yunkus.com/demo/mobile-touch-event/multi-finger-touchmove.html 查看 touchmove 事件觸發時的效果,touchmove 事件觸發後 changedTouches 裡的 touch 對象就不只一個了,而是跟其它兩個 TouchList 列表一樣。

訪問 http://yunkus.com/demo/mobile-touch-event/multi-finger-touchend.html 查看 touchend 事件觸發時的效果,touchmove 事件觸發後就只有  changedTouches 裡有 touch 且只有一個 touch 對象了,不管你同時在螢幕上放了多少根手指,這個 touch 對象對應的是你最後一次離開螢幕的那根手指。

上面的三個 demo 都會輸出事件觸發時的 touches 、targetTouches 和 changedTouches 裡的 identifier 值,以及一個clientX 值。clientX 用於讓你通過 x 的座標來判斷哪根手指對應哪個 identifier 的。對於 touchstart 事件而言,因為 changedTouches 裡總是儲存一個 touch 對象,所以沒有遍曆,而是直接通過下標訪問。從上面我們可以得知有 touchstart 事件中 touches 、targetTouches 和 changedTouches 是有區別的:changedTouches 下只有一個 touch 對象,這個對象對應著觸發事件最後一根發生改變(比如:最後觸控螢幕幕)的手指。這也就是為什麼 changedTouches 裡只有一個 touch 對象的原因,因為某一時刻下總是只有一個手指在變化。

但是也不能以偏蓋全,因為 touchmove 事件中的 changedTouches 裡就不只一個,而是跟 touches 和 targetTouches 同樣有多個 touch 對象。

正如前面所說的 touchend 只有 changedTouches 列表裡只有一個 touch 對象,這個對象對應著最後一根手指發生的改變(比如:最後離開螢幕)的手指。

通過研究單指操作跟多指操作,就可以讓我們對 touch 事件瞭解得更加立體,到位。

預設事件

在移動端手指操作時會預設觸發一些行為,比如:滾動,縮放。上面的例子是沒有阻止觸摸事件的預設行為的。所以當你測試上面 multi-finger-touchmove.html 這個例子時,你會發現有時候你會感到很無助,頁面很容易發生縮允許存取為,甚至影響到測試效果。要想阻止觸摸事件的預設行為也非常地簡單只需要添加如下代碼就可以了:

document.addEventListener("touchstart", function (ev) {    ev.preventDefault();});

添加觸摸事件的阻止預設行為的好處也不僅僅只有這一個。

1.在IOS 10 下設定 meta 禁止使用者縮放是沒有效果的,使用ev.preventDefault(); 就可以實現禁止使用者縮放頁面。

2.解決 IOS 10 下溢出隱藏(不起作用)的問題。

3.禁止系統預設的捲軸(如:橫向捲軸)、以及橡皮筋效果。

4.禁止長按選中文字、選中圖片、系統預設菜單。

5.解決點透問題。

雖然有那麼多好處,需要注意的是此時也會帶來一些問題,比如:input 不能擷取焦點了。不過你可以通過單獨的給 input 標籤添加 touchstart 事件,並且阻止其冒泡就可以讓 input 標籤重生了。

var inputObj = document.getElementsByTagName("input")[0];document.addEventListener("touchstart", function (ev) {    ev.preventDefault();});inputObj.addEventListener("touchstart", function (ev) {    ev.stopPropagation();});

這裡有一個 Demo,通過 touch 的相關事件實現的一個移動端焦點圖轉場效果 :http://yunkus.com/demo/mobile-touch-event/。

移動端觸摸(touch)事件

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.