H5多点触控原理以及对多点触控的追踪
文章目錄
- 接觸點類Touch
- 觸摸事件
- 接觸點的生命周期類
- 多點觸控的追蹤器
- 拋磚引玉
對于PC端,我們的點擊事件比較簡單,因為鼠標指針只有一個。
但是對于移動端來說,存在多個接觸點同時操作的情況,這種情況就是我們今天要研究的主題 – 多點觸控。
接觸點類Touch
移動端的任何觸摸都會觸發一個事件,該事件會攜帶一個touchList列表來表示:當前有哪些接觸點正在作用于我們的屏幕。
通俗點的解釋,接觸點可以理解為你的手指,touchList列表就代表了當前總共有幾個手指正在與屏幕接觸。
而touchList列表中的每一項都是Touch類的對象,它包含了我們手指與屏幕接觸的必要信息:接觸點的位置、壓力大小、接觸面積等等。
所以,在介紹之前,我們必須要先了解這個類。它代表的是屏幕上接觸的點。具體屬性值如下:
// Touch類 屬性說明// 接觸點的唯一標識,每個接觸點的id在接觸過程中都是唯一的,即每個手指都會分配一個id `identifier` // 接觸點的位置信息,這幾個屬性與pc端是一樣的 `clientX:0` `clientY:0` `pageX:0` `pageY:0` `screenX:0` `screenY:0`// 接觸點的壓力值大小 0.0-1.0之間 `force:0`// 這三個參數指示了包含接觸點的最小橢圓 `radiusX:0` //橢圓x軸長 `radiusY:0` //橢圓y軸長 `rotationAngle:0` // 橢圓旋轉角度// 接觸點接觸的HTML對象 `target:DocumentHTMLDom`讀者朋友可以看出來,上面這個類,準確的定義了一個接觸點的各種屬性。那么,在哪才能得到這些接觸點的對象呢?
聰明如你,估計已經猜到了,那就是在觸摸事件中。
注意屬性中的identifier哦~非常重要!
觸摸事件
上面也提到了,Touch類只會存在于觸摸事件里。常用的觸摸事件有touchestart、touchmove、touchend、touchcacel。
它們都是TouchEvent類的實例,TouchEvent類的屬性包含了前面介紹的接觸點Touch實例列表。我們主要關注它的三個屬性即可,如下:
TouchEvent.changedTouches
這是一個只讀屬性,是一個TouchList對象,它包含了代表所有從上一次觸摸事件到此次事件過程中,狀態發生了改變的觸點的 Touch 對象。
TouchEvent.touches
這是一個只讀屬性,是一個TouchList對象,它包含了所有當前正在接觸的接觸點Touch對象,無論它們的起始于哪個element上,也無論它們狀態是否發生了變化。
TouchEvent.targetTouches
這是一個只讀屬性,是一個TouchList對象,它包含了如下觸點的 Touch 對象:觸摸起始于當前事件的目標 element 上,并且仍然沒有離開觸摸平面的觸點。
完整的屬性列表,可以參考MDN文檔,https://developer.mozilla.org/zh-CN/docs/Web/API/TouchEvent。
對于手勢庫來說,這幾個TouchList屬性已經夠用了。
接觸點的生命周期類
想一想我們一個手指在屏幕上滑動的過程:開始接觸 -> 接觸時的移動 -> 接觸結束。
這實際上就是一個接觸點的生命周期,我們來為這一過程定義一個數據結構吧。
/*** touch事件的生命周期類* @constructor* */ var TouchLife = (function () {var id = 0;return function () {/*** 生命周期的id* @type {number}* */this.id=id++;/*** 開始的touch事件* @type {Touch}* */this.startTouchEvent = null;/*** 結束的touch事件* @type {Touch}* */this.endTouchEvent = null;/*** 移動的touch事件* @type {Touch[]}* */this.moveTouchEventList = [];}; })();生命周期的開始和結束都只需要一個Touch對象,而移動可以多次移動,需要一個TouchList來保存。
另外附加了一個生命周期的ID,用來唯一標識一次生命周期。
多點觸控的追蹤器
有了接觸點的生命周期,我們還需要一個追蹤器,用來追蹤多個接觸點的生命周期。
試想一下,對于PC,只有一個鼠標指針,我們能很好的記錄它的運行軌跡。
但是對于移動端,當存在多個接觸點同時作用于屏幕時,怎么來記錄他們的運行軌跡呢?
這就是追蹤器的主要功能:記錄接觸點的運行軌跡。
除此之外,在某個生命周期狀態變化的時候,追蹤器應該能通知應用程序做處理。
這里直接給出它的實現:
/*** touch事件追蹤器* @param opt* @param opt.target 被追蹤的dom對象* @constructor*/ function TouchLifeTracer(opt) {/*** 追蹤的對象* */this.target = opt.target;/*** 作用于target的所有生命周期,包含存活和死亡的周期* */this._lifeList = [];/*** 當前存活的生命周期,正在與target接觸的觸摸點生命周期* */this.currentLifeList = [];/*** 某個生命周期開始* @type {function}* @param callback(life)* */this.onlifestart = null;/*** 某個生命周期狀態變更* @type {function}* @param callback(life)* */this.onlifechange = null;/*** 某個生命周期開始* @type {function}* @param callback(life)* */this.onlifeend = null;/*** 添加生命周期* @param life {TouchLife} 生命周期* @return {*}*/this.addLife = function (life) {this._lifeList.push(life);};/*** 根據identifier查找生命周期,此方法只能在生命周期內使用* @param identifier* @return {*}*/this.findCurrentLifeByTouchID = function (identifier) {for(var i=0;i<this.currentLifeList.length;i++){var life = this.currentLifeList[i];if(life.startTouchEvent.identifier===identifier)return life;}};/*** 根據touchID刪除當前觸摸的生命周期* @param identifier* @return {boolean}*/this.deleteCurrentLifeByTouchID = function (identifier) {for(var i=0;i<this.currentLifeList.length;i++){var life = this.currentLifeList[i];if(life.startTouchEvent.identifier===identifier){this.currentLifeList.splice(i,1);return true;}}return false;};/*** 初始化*/this.init = function () {var self = this;this.target.addEventListener("touchstart",function (e) {e.preventDefault();var touchLife = new TouchLife();touchLife.startTouchEvent = e.changedTouches[0];self.addLife(touchLife);self.currentLifeList.push(touchLife);self.onlifestart && self.onlifestart(life);});this.target.addEventListener('touchmove',function (e) {e.preventDefault();var touches = e.changedTouches;for(var i=0;i<touches.length;i++){var touch = touches[i];var life = self.findCurrentLifeByTouchID(touch.identifier);life.moveTouchEventList.push(touch);self.onlifechange && self.onlifechange(life);}});this.target.addEventListener('touchend',function (e) {e.preventDefault();var touch = e.changedTouches[0];var life = self.findCurrentLifeByTouchID(touch.identifier);life.endTouchEvent = touch;self.deleteCurrentLifeByTouchID(touch.identifier);self.onlifeend && self.onlifeend(life);});};this.init(); }上面這個算是最簡單的追蹤器了,它僅僅包含了最基本的屬性和方法。包括:
- 幾個必要的屬性:追蹤器作用的對象、存活的生命周期、全部生命周期。
- 幾個必要的方法:新增生命周期、刪除生命周期、查找生命周期、追蹤器的初始化。
- 幾個必要的事件:生命周期的開始、生命周期的變化、生命周期的結束。
存活的生命周期,對應于我們正在接觸屏幕的手指。
而全部生命周期,對應于我們所有接觸屏幕的歷史記錄。
有了這個追蹤器,我們在監控多點觸控的時候,就相當的方便了。比如:
// 獲取元素 var a1 = document.getElementById('canvasID');// 初始化 var tracer = new TouchLifeTracer({target:a1}); tracer.onlifestart = function (life) {//todo with life startconsole.log('檢測到一個新的接觸點觸摸元素'); }; tracer.onlifeend = function (life) {//todo with life endconsole.log('檢測到一個接觸點離開元素'); };拋磚引玉
有了這個追蹤器,是不是就可以自己擼一個手勢庫出來了呢?答案是肯定的。
手勢庫的原理,也就是多點觸控+手勢的判斷條件,僅此而已!
百度搜手勢庫比較靠前的,比如Hammer.js,比如AlloyFinger,這些庫都是基于這兩點基礎知識來對手勢進行模擬的。
始終相信,別人能做到的,我們也能做到!
那么,下篇文章我們就來真正的實現一個手勢庫,敬請期待!
覺得有用,還請點贊收藏!
勵志前端,CSDN唯一賬號!關注我,帶你了解更多前端知識!
總結
以上是生活随笔為你收集整理的H5多点触控原理以及对多点触控的追踪的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Senparc.Weixin.MP SD
- 下一篇: 教育企业该如何搭建私域流量池