Hammer.js分析(二)——manager.js

“Manager”是所有识别器实例的容器,它为你设置的元素安装了交互事件监听器,并设置了触摸事件特性。

manager.js中的代码会涉及到input.js和recoginzer.js中的内容,这里会先做大致的流程分析,具体分析会在接下来的文章中详谈。

一、Manager构造函数

初始化流程如下所示:

对应的函数代码如下所示:

function Manager(element, options) {
  this.options = assign({}, Hammer.defaults, options || {});//拷贝设置
  this.options.inputTarget = this.options.inputTarget || element;//目标元素
  this.handlers = {};//事件组,例如自定义的tap事件等
  this.session = {};//全局属性缓存,例如当前Recognizer对象
  this.recognizers = [];//当前绑定的Recognizer对象数组,通过add方法添加
  this.element = element;

  this.input = createInputInstance(this);//根据特性初始化相关的input子类 此函数在input.js中
  this.touchAction = new TouchAction(this, this.options.touchAction);

  toggleCssProps(this, true);//执行Hammer中的cssProps设置
  //初始化需要执行的识别器
  each(this.options.recognizers, function(item) {
    var recognizer = this.add(new(item[0])(item[1]));
    item[2] && recognizer.recognizeWith(item[2]);
    item[3] && recognizer.requireFailure(item[3]);
  }, this);
}

二、Manager对象中的函数

1)set(options)

修改Manager对象的相关参数,可以在需要的时候更新touchAction的值。

如果改动了“inputTarget”参数,input对象就要重新初始化。

mc.set({ touchAction: TOUCH_ACTION_PAN_X, inputTarget: null });

2)get(Recognizer|String)、add(Recognizer) 和 remove(Recognizer|String)

get:通过事件名(tap、pinch等)获取recognizers数组中相应的识别器,如果传入的是识别器则直接返回这个识别器

add:添加识别器到recognizers数组中。会做判断其是否存在,如果存在就先移除,然后再做添加,并执行touchAction对象的update方法,上面有讲到。

remove:先通过get方法获取到相应的识别器,再判断是否存在,最后recognizers数组做splice操作,并执行touchAction对象的update方法。

3)on(events, handler) 和 off(events, [handler])

on:绑定事件,通过空格隔开,可以绑定多个事件,splitStr就是通过空格字符串的函数。事件都会push到handlers[event]数组中,key就是事件名

off:移除绑定了的事件,会判断是否传入了handler,没有就直接delete,有的话还要搜索下是否在handlers[event]数组中,有就做splice

4)recognize(inputData)

执行recognizers数组。input.js中的inputHandler函数会调用这个方法,inputData是自定义事件对象,内容如下:

方法的大致流程如下:

下面的代码涉及了多处Recognizer中概念,下面的代码就先看个大致过程:

recognize: function(inputData) {
  var session = this.session;//全局缓存,在Input对象中会用到
  if (session.stopped) {//在stop方法中可以设置,有两个选项
    return;
  }
  // 执行CSS属性“touch-action”的 polyfill
  this.touchAction.preventDefaults(inputData);

  var recognizer;
  var recognizers = this.recognizers;//在Hammer或外面调用add添加的识别器数组

  // 每个识别器有四个状态:BEGAN, CHANGED, ENDED 和 RECOGNIZED
  // 如果curRecognizer还没设置就是 `null`
  var curRecognizer = session.curRecognizer;

  // 如果是一个新的或当前识别器的状态为RECOGNIZED,就重置为null
  if (!curRecognizer || (curRecognizer && curRecognizer.state & STATE_RECOGNIZED)) {
    curRecognizer = session.curRecognizer = null;
  }

  var i = 0;
  while (i < recognizers.length) {
    recognizer = recognizers[i];
    // 满足下面的条件就执行识别器的recognize方法,否则重置
    // 1.   缓存的stopped不能是FORCED_STOP状态
    // 2.   curRecognizer还未设置或curRecognizer与循环中的recognizer相同
    // 3.   recognizer设置了可以与curRecognizer同时执行,这里有个识别器recognizeWith的概念后面会讲到
    if (session.stopped !== FORCED_STOP && ( // 1
        !curRecognizer || recognizer == curRecognizer || // 2
        recognizer.canRecognizeWith(curRecognizer))) { // 3
      recognizer.recognize(inputData);
    } else {
      recognizer.reset();
    }

    // curRecognizer为空,并且recognizer的状态是STATE_BEGAN、STATE_CHANGED和STATE_ENDED中的一个
    if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) {
      curRecognizer = session.curRecognizer = recognizer;//设置curRecognizer与session.curRecognizer
    }
    i++;
  }
}

在上面的代码中会涉及到recoginzer.js中的“recognizeWith”,这里简单介绍下“recognizeWith”和“requireFailure”。

1)recognizeWith:其实就是让几个事件同时触发,例如旋转的时候还要做放大。

2)requireFailure:正好相反,例如双击的时候不触犯单机的事件。

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

时间: 2024-10-26 11:34:25

Hammer.js分析(二)——manager.js的相关文章

js随笔(二):JS String Method

String Methods and Properties String.length:  length() 返回字符串长度 var txt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; var sln = txt.length; Finding a String in a String:  indexOf(str,[, index]) 在字符串中找到你想要的字符串,indexOf返回的位置是你搜索字符串第一次出现的位置. var str = "Please

Hammer.js分析(三)——input.js

input.js是所有input文件夹中类的父类,浏览器事件绑定.初始化特定的input类.各种参数计算函数. Input父类和其子类就是在做绑定事件,各种参数计算.整合.设置等返回自定义事件对象,交给识别器的相关对象使用. 一.Input父类 Input相当于一个抽象类,对象中总共有3个方法 1)handler(ev) 这相当于一个抽象方法,在上图中的6个子对象里,都会实现这个方法. ev是事件对象(不是自定义的那个),例如触屏事件中就是 TouchEvent. 2)init()与destro

Hammer.js分析(一)——基础结构

从github上面将源码下载下来,会发现有个src文件夹.当前版本是2.0.6. 总的结构如下: 一.常量 这里将常量全部列在一起是可以在对比源码的时候,更方便的查看相应内容. var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o'];//前缀 var TEST_ELEMENT = document.createElement('div');//测试元素 var TYPE_FUNCTION = 'function';//函数 //-

Hammer.js分析(四)——recognizer.js

不同识别器会使用不同逻辑,根据从相关Input类获取到的事件对象和事件,实现自定义的触屏事件,例如tap.pinch等. 一.继承关系 Recognizer与前面的Input一样,也相当于是个抽象类. 从上图中可以看到,6个子类都会先继承AttrRecognizer类,因为AttrRecognizer类中的2个方法可以共用,attrTest与process,如果自己不实现,就可以直接调用. 二.识别器状态 每个识别器的初始状态是 “POSSIBLE”,每个识别器都会有一个状态周期. 例如做一次

玩转Node.js(二)

玩转Node.js(二) 先来回顾上次的内容,上一次我们使用介绍了Node.js并写了第一个服务器端的Hello World程序,在这个Hello World程序中,请求自带的http模块并将其赋给http变量,然后调用http模块的createServer函数,这个函数会返回一个对象,这个对象有一个叫做listen的方法,而这个方法有一个数值参数,指定这个HTTP服务器监听的端口号,我们当时定义的是8888端口号.那么为什么看起来有些复杂呢?那是因为我们向createServer函数传递了一个

初探JavaScript(二)——JS如何动态操控HTML

除去五一三天,我已经和<JavaScript Dom编程艺术>磨合了六天,第一印象很好.慢慢的,我发现这是一块排骨,除了肉还有骨头.遇到不解的地方就会多看几遍,实在不懂的先跳过,毕竟,初次接触JS,没有必要花费过多时间去钻死胡同,先混个脸熟,以后再来拜访也未尝不可嘛.就这样,踉踉跄跄.囫囵吞枣似的已经过五关斩六将,到达第十一章. 书中有几个章节并没有从语法.技术等层面介绍JavaScript,而是站在一个全局的角度,立足编程原则和习惯道破了我们该如何看待和使用这门语言,主要有以下几点: Jav

JS的二维数组

今天,记录一下JS的二位数组,并附上例题. 一.二维数组的本质:数组中的元素又是数组. 其实,我们都见过这样的二维数组,只不过没在意罢了,例如: var arr = [[1,2,4,6],[2,4,7,8],[8,9,10,11],[9,12,13,15]] //这就是一个二位数组arr[2][3]; // 11 注意:表示第三列第4行所在的元素.角标从0开始 二.下面介绍二维数组的初始化 记住了二维数组的本质,初始化也难不倒我们了.看一下实例 实例一: var arr = [[1,2],[a,

advanced JavaScript Skills ——Require.js(二)

咱们在上一篇博客中写道,使用RequireJS的好处,以及一些简单的介绍.还有使用它的好处: 1.防止js加载阻塞页面渲染 2.可以通过程序调用的方式加载js文件.就不用写辣么多的JavaScript的引用了.界面整洁美观了更加.如果你的界面像下面一样,可以考虑一下,使用Require.js模块化加载的方式来改造提高你的前台代码的质量! 今天,咱们来看看RequireJS真正的看家本领.她是如何解决模块之间的依赖性的问题的. 一.RequireJs的加载 使用require.js的第一步,是先去

JS学习二

函数作用域和声明提前 var scope = 'global'; function f() { console.info(scope);   //输出undefined var scope = 'local'; console.info(scope);  //输出 local } 上述代码等价于 function f() { var scope; console.info(scope); scope = 'local'; console.info(scope); } 将函数内的变量声明"提前&q