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,选取绝对值大的那个 |