zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    后缀数组模板
    UVALive
    蓝桥杯 拿糖果
    蓝桥杯 矩阵乘法(区间DP)
    51nod 矩阵乘法
    13.boost有向无向图邻接表表示
    12.boost有向图无向图(矩阵法)
    11.使用boostregex遭遇无法打开libboost_regex-vc120-mt-sgd-1_62.lib的问题
    10.ref regex unordered_set smartpoint
    9.variant move function change_cast
  • 原文地址:https://www.cnblogs.com/strick/p/5185077.html
Copyright © 2011-2022 走看看