不同识别器会使用不同逻辑,根据从相关Input类获取到的事件对象和事件,实现自定义的触屏事件,例如tap、pinch等。

一、继承关系

Recognizer与前面的Input一样,也相当于是个抽象类。

从上图中可以看到,6个子类都会先继承AttrRecognizer类,因为AttrRecognizer类中的2个方法可以共用,attrTest与process,如果自己不实现,就可以直接调用。

二、识别器状态

每个识别器的初始状态是 “POSSIBLE”,每个识别器都会有一个状态周期。

例如做一次 “tap” 操作,浏览器使用了touch相关操作模拟: touchstart -> touchend,而状态是从 STATE_FAILED -> STATE_ENDED。

6种操作的状态走向图如下:

在 manage.js 中recognize方法,就是在根据识别器状态,来给 “curRecognizer” 与 “session.curRecognizer” 赋值,缓存这个当前周期内的状态。

如果识别器的状态是FAILED, CANCELLED 或者 RECOGNIZED (等同于 ENDED),那就要重置为 POSSIBLE,或结束当前识别器周期,让下一个识别器来。

下面的1,2,4,8等这样取值是为了方便位运算。

 var STATE_POSSIBLE = 1;
var STATE_BEGAN = 2;
var STATE_CHANGED = 4;
var STATE_ENDED = 8;
var STATE_RECOGNIZED = STATE_ENDED;
var STATE_CANCELLED = 16;
var STATE_FAILED = 32;

三、Recognizer父类中的抽象方法

1. process(inputData)

返回识别器的状态,各个子类的实现逻辑都会不同,如果没有实现,就会引用通用父类AttrRecognizer中的process。

2. getTouchAction()

获取“touch-action”的属性数组

 var TOUCH_ACTION_COMPUTE = 'compute';
var TOUCH_ACTION_AUTO = 'auto';
var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented
var TOUCH_ACTION_NONE = 'none';
var TOUCH_ACTION_PAN_X = 'pan-x';
var TOUCH_ACTION_PAN_Y = 'pan-y'; getTouchAction: function() {
return [TOUCH_ACTION_MANIPULATION];
}

3. reset()

只有 tap.js 与 press.js实现了这个方法

 reset: function() {
clearTimeout(this._timer);
}

四、Recognizer父类中的方法

1)recognizeWith(otherRecognizer)  和 dropRecognizeWith(otherRecognizer)

recognizeWith:就是让当前识别器运行的时候同步运行所给的其它识别器(otherRecognizer),就是让几个操作同时触发,例如结合tap和rotate。

dropRecognizeWith:就是解除这层关系。

tap.recognizeWith(new Hammer.Rotate());

上面的代码中 recognizeWith 在内部会调用三次,下面的第17行代码,促使这个方法调用3次。

 /**
* @param {Recognizer|Array|String} otherRecognizer
* @returns {Recognizer} this
*/
recognizeWith: function(otherRecognizer) {
//支持一个识别器组成的数组来作为参数
if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) {
return this;
} var simultaneous = this.simultaneous;
//如果识别器被添加到了Manager上,也支持将其它识别器(otherRecognizer)的事件名(字符串形式)来作为参数
otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
if (!simultaneous[otherRecognizer.id]) {
//保存到 simultaneous 数组中
simultaneous[otherRecognizer.id] = otherRecognizer;
otherRecognizer.recognizeWith(this);//调用otherRecognizer的方法
}
return this;
}

manager.js中recognize方法内调用了个 canRecognizeWith 的方法,里面其实就是在根据识别器的ID判断是否存在。

 canRecognizeWith: function(otherRecognizer) {
return !!this.simultaneous[otherRecognizer.id];
}

2)requireFailure(otherRecognizer)  和 dropRequireFailure(otherRecognizer)

requireFailure:与recognizeWith相反,在某个操作的时候,不执行otherRecognizer。也就是只有当其它识别器(otherRecognizer)无效时才执行该识别器。

dropRequireFailure:解除这层关系。

 /**
* @param {Recognizer|Array|String} otherRecognizer
* @returns {Recognizer} this
*/
requireFailure: function(otherRecognizer) {
if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) {
return this;
} var requireFail = this.requireFail;
otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
if (inArray(requireFail, otherRecognizer) === -1) {
requireFail.push(otherRecognizer);//维护一个requireFail数组
otherRecognizer.requireFailure(this);
}
return this;
}

这个 requireFail 数组在 Recognizer.canEmit 方法中会被调用,返回一个boolean值,用于在 Recognizer.tryEmit 是否能执行子类中的 emit 方法。

在第一篇《基础结构》的操作流程图中,有调用 emit 方法,子类是 Tap。

tryEmit: function(input) {
if (this.canEmit()) {
return this.emit(input);
}
// it's failing anyway
this.state = STATE_FAILED;
},
canEmit: function() {
var i = 0;
while (i < this.requireFail.length) {
if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) {
return false;
}
i++;
}
return true;
}

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

Hammer.js分析(四)——recognizer.js的更多相关文章

  1. js分析 快速定位 js 代码, 还原被混淆压缩的 js 代码

    -1.目录 0.参考 1.页面表现 2. 慢镜头观察:低速网络请求 3. 从头到尾调试:Fiddler 拦截 index.html 并添加 debugger; 4. 快速定位 js 代码 5. 还原被 ...

  2. angular源码分析:injector.js文件分析——angular中的依赖注入式如何实现的(续)

    昨天晚上写完angular源码分析:angular中jqLite的实现--你可以丢掉jQuery了,给今天定了一个题angular源码分析:injector.js文件,以及angular的加载流程,但 ...

  3. bootstrap学习总结-js组件(四)

    这次我们来看下js组件的使用,本篇文章会有点长,希望大家可以耐心看,相信收获会有不少.不少园友加我好友,表示喜欢我写文字的风格,简单明了,这里,再次谢谢你们的支持.一方面,博主自身技术有限,写的东西都 ...

  4. 前端总结·基础篇·JS(四)异步请求及跨域方案

    前端总结系列 前端总结·基础篇·CSS(一)布局 前端总结·基础篇·CSS(二)视觉 前端总结·基础篇·CSS(三)补充 前端总结·基础篇·JS(一)原型.原型链.构造函数和字符串(String) 前 ...

  5. js分析 汽_车_之_家 js生成css伪元素 hs_kw44_configUS::before

    0.参考 https://developer.mozilla.org/zh-CN/docs/Web/CSS/Pseudo-elements https://developer.mozilla.org/ ...

  6. js分析 天_眼_查 字体文件

    0. 参考 js分析 猫_眼_电_影 字体文件 @font-face 1. 分析 1.1 定位目标元素 1.2 查看网页源代码 1.3 requests 请求提取得到大量错误信息 对比猫_眼_电_影抓 ...

  7. 潭州课堂25班:Ph201805201 爬虫基础 第十四课 js破解 (课堂笔记)

    打断点 找要的数据 鼠标的点击事件 新浪微博登录 表单提交分析 : 先佃输入错误密码开始调式 f10 往下走, f11 进入函数 sh + f11 跳出函数 # -*- coding: utf-8 - ...

  8. 玩转Node.js(四)-搭建简单的聊天室

    玩转Node.js(四)-搭建简单的聊天室 Nodejs好久没有跟进了,最近想用它搞一个聊天室,然后便偶遇了socket.io这个东东,说是可以用它来简单的实现实时双向的基于事件的通讯机制.我便看了一 ...

  9. 后端程序员看前端想死(二)进入页面之后js分析

    在上一篇中分析了一下以网页的组成.header中引入的乱七八糟的东西,现在进入到js中进行分析了 tuhooo啊,你是要搞前端了么? nonono,好玩,学一下 打开页面之后执行js的几种方法 直接写 ...

  10. js 第四章 cookie的操作

    js 第四章 cookie的操作 一.学习要点 掌握cookie的简单应用 二. js 第四章 cookie的操作 了解cookie 什么是cookie? cookie 是存储于访问者的计算机中的变量 ...

随机推荐

  1. txt文本变成html

    file_name = 'x.txt' f = open(file_name,'r') file_result = 'x.html' str_head = " LINE CI UTIL&qu ...

  2. mysql如何在一个字段后面加个字符?

    update city set 字段=concat(字段,'内容');

  3. #1094 : Lost in the City

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 Little Hi gets lost in the city. He does not know where he is ...

  4. eclipse创建Maven-web项目(-)

    一.new----other----maven----maven project 二.next 三.next(选择maven-archetype-webapp) 四.填写相应的信息,Packaged是 ...

  5. Raft 为什么是更易理解的分布式一致性算法

    一致性问题可以算是分布式领域的一个圣殿级问题了,关于它的研究可以回溯到几十年前. 拜占庭将军问题 Leslie Lamport 在三十多年前发表的论文<拜占庭将军问题>(参考[1]). 拜 ...

  6. JavaScript异步编程原理

    众所周知,JavaScript 的执行环境是单线程的,所谓的单线程就是一次只能完成一个任务,其任务的调度方式就是排队,这就和火车站洗手间门口的等待一样,前面的那个人没有搞定,你就只能站在后面排队等着. ...

  7. Hadoop学习笔记—13.分布式集群中节点的动态添加与下架

    开篇:在本笔记系列的第一篇中,我们介绍了如何搭建伪分布与分布模式的Hadoop集群.现在,我们来了解一下在一个Hadoop分布式集群中,如何动态(不关机且正在运行的情况下)地添加一个Hadoop节点与 ...

  8. Hadoop学习笔记—17.Hive框架学习

    一.Hive:一个牛逼的数据仓库 1.1 神马是Hive? Hive 是建立在 Hadoop 基础上的数据仓库基础构架.它提供了一系列的工具,可以用来进行数据提取转化加载(ETL),这是一种可以存储. ...

  9. Windows Azure Storage (6) Windows Azure Storage之Table

    <Windows Azure Platform 系列文章目录> 最近想了想,还是有必要把Windows Azure Table Storage 给说清楚. 1.概念 Windows Azu ...

  10. 《Entity Framework 6 Recipes》翻译系列(2) -----第一章 开始使用实体框架之使用介绍

    Visual Studio 我们在Windows平台上开发应用程序使用的工具主要是Visual Studio.这个集成开发环境已经演化了很多年,从一个简单的C++编辑器和编译器到一个高度集成.支持软件 ...