Hammer.js分析——recognizer.js

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hammer.js分析——recognizer.js相关的知识,希望对你有一定的参考价值。

不同识别器会使用不同逻辑,根据从相关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等这样取值是为了方便位运算。

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

 

三、Recognizer父类中的抽象方法

1. process(inputData)

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

 

2. getTouchAction()

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

 1 var TOUCH_ACTION_COMPUTE = ‘compute‘;
 2 var TOUCH_ACTION_AUTO = ‘auto‘;
 3 var TOUCH_ACTION_MANIPULATION = ‘manipulation‘; // not implemented
 4 var TOUCH_ACTION_NONE = ‘none‘;
 5 var TOUCH_ACTION_PAN_X = ‘pan-x‘;
 6 var TOUCH_ACTION_PAN_Y = ‘pan-y‘;
 7 
 8 getTouchAction: function() {
 9     return [TOUCH_ACTION_MANIPULATION];
10 }

 

3. reset()

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

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

 

四、Recognizer父类中的方法

1)recognizeWith(otherRecognizer)  和 dropRecognizeWith(otherRecognizer)

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

dropRecognizeWith:就是解除这层关系。

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

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

 1 /**
 2  * @param {Recognizer|Array|String} otherRecognizer
 3  * @returns {Recognizer} this
 4  */
 5 recognizeWith: function(otherRecognizer) {
 6   //支持一个识别器组成的数组来作为参数
 7   if (invokeArrayArg(otherRecognizer, ‘recognizeWith‘, this)) {
 8     return this;
 9   }
10 
11   var simultaneous = this.simultaneous;
12   //如果识别器被添加到了Manager上,也支持将其它识别器(otherRecognizer)的事件名(字符串形式)来作为参数
13   otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
14   if (!simultaneous[otherRecognizer.id]) {
15     //保存到 simultaneous 数组中
16     simultaneous[otherRecognizer.id] = otherRecognizer;
17     otherRecognizer.recognizeWith(this);//调用otherRecognizer的方法
18   }
19   return this;
20 }

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

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

 

2)requireFailure(otherRecognizer)  和 dropRequireFailure(otherRecognizer)

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

dropRequireFailure:解除这层关系。

 1 /**
 2  * @param {Recognizer|Array|String} otherRecognizer
 3  * @returns {Recognizer} this
 4  */
 5 requireFailure: function(otherRecognizer) {
 6   if (invokeArrayArg(otherRecognizer, ‘requireFailure‘, this)) {
 7     return this;
 8   }
 9 
10   var requireFail = this.requireFail;
11   otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
12   if (inArray(requireFail, otherRecognizer) === -1) {
13     requireFail.push(otherRecognizer);//维护一个requireFail数组
14     otherRecognizer.requireFailure(this);
15   }
16   return this;
17 }

这个 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的主要内容,如果未能解决你的问题,请参考以下文章

Hammer.js分析——基础结构

Hammer.js分析——input.js

使用 Hammer.js 捏缩放

使用 Hammer.js 时移动 Safari 崩溃

如何在特定视口上设置触摸手势/hammer.js 处于活动状态?

hammer.js 拖动不开始'直到手指停止在 ipad 屏幕上