input.js是所有input文件夾中類的父類,瀏覽器事件綁定、初始化特定的input類、各種參數計算函數。
Input父類和其子類就是在做綁定事件,各種參數計算、整合、設置等返回自定義事件對象,交給識別器的相關對象使用。
一、Input父類
Input相當於一個抽象類,對象中總共有3個方法
1)handler(ev)
這相當於一個抽象方法,在上圖中的6個子對象里,都會實現這個方法。
ev是事件對象(不是自定義的那個),例如觸屏事件中就是 TouchEvent。
2)init()與destroy()
綁定事件,在各個子對象都會設置:
evEl、evTarget 或 evWin 事件類型字符串,字符串中有空格就是多個事件。
element、target 或 getWindowForElement(this.element) 就是需要綁定事件的對象。
domHandler 是在構造函數中定義的,就是執行子集重寫過的 handler 方法。里面有個判斷,“enable” 可以控制是否執行事件。
this.domHandler = function(ev) { if (boolOrFn(manager.options.enable, [manager])) { self.handler(ev); } };
二、input.js中的函數
1)createInputInstance(manager)
根據特性選擇創建對象,可指定也可以根據瀏覽器特性自動綁定。在Manager的構造函數中會被調用。
var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i; var SUPPORT_TOUCH = ('ontouchstart' in window); var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined; var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent); function createInputInstance(manager) { var Type; var inputClass = manager.options.inputClass;//自定義的函數 if (inputClass) { Type = inputClass; } else if (SUPPORT_POINTER_EVENTS) { Type = PointerEventInput; } else if (SUPPORT_ONLY_TOUCH) { Type = TouchInput; } else if (!SUPPORT_TOUCH) { Type = MouseInput; } else { Type = TouchMouseInput; } return new(Type)(manager, inputHandler);//inputHandler是input.js中的一個函數 }
2)inputHandler(manager, eventType, input)
a. 在每個子類(touch.js中的TouchInput等)的構造函數中,都會執行“Input.apply(this, arguments);”,調用父類(input.js中的Input)的構造函數。
b. 在上一個函數中會將 inputHandler 傳入到子類的構造函數中,這樣的話父類中的 callback 就等於是 inputHandler。
c. 每個子類中的 handler 方法都會調用 callback 函數。
在每個子類中都會有類似的Map值,key是事件名,value是整數:
var TOUCH_INPUT_MAP = { touchstart: INPUT_START, touchmove: INPUT_MOVE, touchend: INPUT_END, touchcancel: INPUT_CANCEL };
函數內容如下:
function inputHandler(manager, eventType, input) { var pointersLen = input.pointers.length; var changedPointersLen = input.changedPointers.length; var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0)); var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0)); //設置自定義事件對象的參數 input.isFirst = !!isFirst; input.isFinal = !!isFinal; if (isFirst) { manager.session = {}; } //設置 eventType,例如 'touchstart, mouseup, pointerdown'的對應整數,通過上面的Map值獲取到 input.eventType = eventType; //計算旋轉、比例、角度、距離等信息 computeInputData(manager, input); //執行隱藏的事件,這個在會在每個事件中調用,例如 'touchstart, mouseup, pointerdown'等 manager.emit('hammer.input', input); manager.recognize(input);//執行Manager對象中的recognize方法 manager.session.prevInput = input; }
3)computeDeltaXY(session, input)
經過計算的X與Y軸坐標,有正數和負數,以某個點為原點,畫坐標軸。如下圖所示:
以prevDelta的X和Y作為原點,center中的X和Y會隨着移動而改變,offset就是第一次接觸屏幕的點的clientX與clientY。
center是通過函數“getCenter(pointers)”獲得的。
4)其他技術函數
1. getCenter(pointers):通過clientX和clientY,以及點的個數,計算所有點的中心坐標,沒有負數
2. getVelocity(deltaTime, x, y):計算兩個點之間的移動速度
3. getDirection(x, y):判斷一個點到另外一個點的移動方向
4. getDistance(p1, p2, props):計算兩個點之間的直線距離
5. getAngle(p1, p2, props):計算兩個點之間的夾角
6. getRotation(start, end):計算兩個點集之間的旋轉度
7. getScale(start, end):計算兩個點集之間的比例
三、自定義的input事件對象
在前面一篇“manager.js”的分析中,提到了自定義事件對象,里面還包括各種計算過的參數。
1)事件對象
2)移動方向常量
之所以是1,2,4,8,16是為了方便位運算。
var DIRECTION_NONE = 1; var DIRECTION_LEFT = 2; var DIRECTION_RIGHT = 4; var DIRECTION_UP = 8; var DIRECTION_DOWN = 16;
3)事件類型常量
var INPUT_START = 1; var INPUT_MOVE = 2; var INPUT_END = 4; var INPUT_CANCEL = 8;
4)具體說明
Name |
Value |
angle |
移動角度 |
center |
多點觸控的中心位置,或者單點的坐標 |
changedPointers |
改變了的觸摸點數組,例如touchend中的事件中的事件對象TouchEvent里的changedTouches |
deltaTime |
交互過程的總時長(ms) |
deltaX |
經過計算后的X軸坐標點(參考computeDeltaXY) |
deltaY |
經過計算后的Y軸坐標點(參考computeDeltaXY) |
direction |
移動方向(參考移動方向常量) |
distance |
移動距離 |
eventType |
事件類型(參考事件類型常量) |
isFinal |
當前交互是否為最后一次(boolean) |
isFirst |
當前交互是否為首次(boolean) |
maxPointers |
最大觸摸點數量 |
offsetDirection |
從起始點算起的移動方向(參考移動方向常量) |
overallVelocityX |
deltaX坐標點的移動速度 |
overallVelocityY |
deltaY坐標點的移動速度 |
overallVelocity |
比較overallVelocityX與overallVelocityY,選取絕對值大的那個 |
pointerType |
觸摸點類型(touch、pen、mouse 或 kinect) |
pointers |
觸摸點數組,例如touchend中事件對象TouchEvent里的touches屬性 |
rotation |
多點觸摸結束時的旋轉數值,若為單點觸摸則為0 |
scale |
多點觸摸結束時的縮放比例,若為單點觸摸則為1 |
srcEvent |
源事件對象(類型為TouchEvent、MouseEvent或PointerEvent) |
target |
接收事件的目標,上圖中就是 document.getElementById('layer') |
timeStamp |
當前時間戳 |
velocityX |
(input.deltaX - last.deltaX)計算后X坐標點的移動速度 |
velocityY |
(input.deltaY - last.deltaY)計算后Y坐標點的移動速度 |
velocity |
比較velocityX與velocityY,選取絕對值大的那個 |
demo源碼下載:
http://download.csdn.net/download/loneleaf1/9429375
參考資料:
http://tech.gilt.com/2014/09/23/five-things-you-need-to-know-about-hammer-js-2-0/
FIVE THINGS YOU NEED TO KNOW ABOUT HAMMER.JS 2.0
http://www.cnblogs.com/iamlilinfeng/p/4239957.html Hammer.js
http://colinued.leanote.com/post/%E7%A7%BB%E5%8A%A8%E7%AB%AF%E6%89%8B%E5%8A%BF%E5%BA%93hammerJS-2.0.4%E5%AE%98%E6%96%B9%E6%96%87%E6%A1%A3%E7%BF%BB%E8%AF%91 移動端手勢庫hammerJS-2.0.4