zoukankan      html  css  js  c++  java
  • 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';//函数
    
    //----------------------------Input----------------------------------------
    var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;//判断移动端的正则
    
    var SUPPORT_TOUCH = ('ontouchstart' in window);//判断是否支持touch事件
    var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined;//判断是否支持指针事件
    var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);//判断是触屏
    
    var INPUT_TYPE_TOUCH = 'touch';
    var INPUT_TYPE_PEN = 'pen';
    var INPUT_TYPE_MOUSE = 'mouse';
    var INPUT_TYPE_KINECT = 'kinect';
    
    var COMPUTE_INTERVAL = 25;
    
    var INPUT_START = 1;//1 2 4 8 16方便使用"与"跟"或"判断
    var INPUT_MOVE = 2;
    var INPUT_END = 4;
    var INPUT_CANCEL = 8;
    
    var DIRECTION_NONE = 1;
    var DIRECTION_LEFT = 2;
    var DIRECTION_RIGHT = 4;
    var DIRECTION_UP = 8;
    var DIRECTION_DOWN = 16;
    
    var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT;
    var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN;
    var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL;
    
    var PROPS_XY = ['x', 'y'];
    var PROPS_CLIENT_XY = ['clientX', 'clientY'];
    
    var MOUSE_ELEMENT_EVENTS = 'mousedown';
    var MOUSE_WINDOW_EVENTS = 'mousemove mouseup';
    
    var POINTER_ELEMENT_EVENTS = 'pointerdown';
    var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel';
    
    var SINGLE_TOUCH_TARGET_EVENTS = 'touchstart';
    var SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel';
    
    var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel';
    
    //----------------------------TouchAction----------------------------------------
    var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction');
    var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined;
    
    // magical touchAction value
    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';
    
    //----------------------------Recognizer----------------------------------------
    var STATE_POSSIBLE = 1;
    var STATE_BEGAN = 2;
    var STATE_CHANGED = 4;
    var STATE_ENDED = 8;
    var STATE_RECOGNIZED = STATE_ENDED;//已完成recognize
    var STATE_CANCELLED = 16;
    var STATE_FAILED = 32;
    
    
    //----------------------------Manager----------------------------------------
    var STOP = 1;
    var FORCED_STOP = 2;

    二、utils.js

    各种工具方法包含其中。

    1)setTimeoutContext:封装了一下setTimeout

    2)invokeArrayArg:遍历数组对象,并执行其中的某个方法

    3)each:遍历一个object对象或数组

    4)deprecate:过时警告与栈追踪

    5)assign:拷贝对象,target中的属性将会覆盖source中的属性。目标ES6中新增了一个Object.assign()特性

    6)extend:用一个或多个其他对象来扩展一个对象,有个bool值“merge”控制是否会覆盖属性

    7)merge:合并对象,dest中的属性将不会覆盖src中的属性

    8)inherit:简单的类继承方法

    9)bindFn:指定作用域执行函数

    10)boolOrFn:传递函数就执行函数,传递布尔值就返回boolean

    11)ifUndefined:传递两个值,第一个值是undefined就返回第二个值,否则返回第一值

    12)addEventListeners:封装了addEventListener方法,可通过空格绑定多个事件

    13)removeEventListeners:移除绑定的事件

    14)hasParent:判断是否有父级元素,返回boolean

    15)splitStr:根据空格分割字符串,返回Array

    16)inStr:判断某个字符串是否被包含,返回boolean

    17)inArray:查找某个值在数组中的位置值,返回int

    18)toArray:通过“Array.prototype.slice.call”将对象转换成数组

    19)uniqueArray:数组去重,返回Array

    20)prefixed:获取加了前缀的属性,没有则返回undefined,前缀包括['', 'webkit', 'Moz', 'MS', 'ms', 'o']

    21)uniqueId:获取唯一值,比较简单就是一个递增的数,返回int

    22)getWindowForElement:获取元素的窗口对象

    三、hammer.js

    1)Hammer方式初始化,带预置“Recognizer”(识别器)数组

    插件的使用方法是先创建一个Hammer对象,代码如下:

    var layer = document.getElementById('layer');
    var mc = new Hammer(layer);

    当new的时候,函数内部其实是初始化了一个Manager对象(上面的manager.js),并初始化默认参数defaults。

    function Hammer(element, options) {
        options = options || {};
        options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset);
        return new Manager(element, options);
    }

    Hammer.defaults.preset”是一个“Recognizer”(识别器)对象数组。

    可以让Manager对象预先安装tap、doubletap、 pan、 swipe、press、 pinch和rotate识别器。

    preset: [
            // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...]
            [RotateRecognizer, {enable: false}],
            [PinchRecognizer, {enable: false}, ['rotate']],
            [SwipeRecognizer, {direction: DIRECTION_HORIZONTAL}],
            [PanRecognizer, {direction: DIRECTION_HORIZONTAL}, ['swipe']],
            [TapRecognizer],
            [TapRecognizer, {event: 'doubletap', taps: 2}, ['tap']],
            [PressRecognizer]
    ]

    2)Manager方式初始化,不带预置

    如果不做上面的识别器预置操作,就需要手动添加相应的识别器对象,例如下面的“Tap”。

    var mc = new Hammer.Manager(layer);
    mc.add(new Hammer.Tap());

    关于manager.js的详细说明将会在下一篇文章做讨论。

    3)expose.js

    在上一段代码中,之所以能够引用“Hammer.Tap”,就是因为这段代码中做了拷贝。

    assign(Hammer, {
      Tap: TapRecognizer,
      Pan: PanRecognizer,
      Swipe: SwipeRecognizer,
      //...省略其他值
    });

    除了拷贝,剩下的代码做模块化声明、全局赋值等。

    四、touchaction.js

    模拟CSS中的一个属性“touch-action”,这个属性兼容性非常差,目前只有Chrome 35+, IE10+支持。

    1)演示

    在“Hammer.defaults”默认参数中有一个“touchAction”属性,这个值可以阻止滚动。用手机扫描下面的二维码体验下这个属性:

    我用UC浏览器打开了这个demo操作页面,滑动到“pan-y”处左右滑动屏幕,页面不会出现左右拖动的情况。在“pan-x”处,上下滑动,屏幕不会跟着滚动。

    这个属性非常有用,比如图片滚动展示, 你要看下一张图,那就得用手指划,如果整个页面跟着划过去,那体验很不好,还可能导致误操作。

    下面的表格是描述设置哪个值比较适合对应的手势操作:

    2)update

     在很多地方都会引用到“this.touchAction.update()”,这个方法里面引用了对象中的另外一个方法“set”。

    update: function() {
        this.set(this.manager.options.touchAction);
    }
    var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction');
    var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined;
    set: function(value) {
      // 自己做计算
      if (value == TOUCH_ACTION_COMPUTE) {
        value = this.compute();
      }
      //支持原生"touch-action"就直接赋值
      if (NATIVE_TOUCH_ACTION && this.manager.element.style) {
        this.manager.element.style[PREFIXED_TOUCH_ACTION] = value;
      }
      this.actions = value.toLowerCase().trim();//缓存属性值,用于后面的polyfill
    }

    五、操作流程图

    var layer = document.getElementById('layer');
    var mc = new Hammer.Manager(layer);
    mc.add(new Hammer.Tap());
    
    mc.on('tap', function(e) {
        layer.style.display = "none";
        e.preventDefault();
    });

    初始化的流程在下一篇文章会有介绍。这里就讲一个点击操作的流程,其中绿色框中的内部逻辑不同操作会各有不同:

    最后一步中handlers中保存的事件就是 mc.on 中的内容。

    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

  • 相关阅读:
    PBR(基于物理的渲染)学习笔记
    iOS应用千万级架构开篇
    iOS应用千万级架构:性能优化与卡顿监控
    iOS应用千万级架构:自动埋点与曝光
    iOS应用千万级架构:存储持久化
    iOS应用千万级架构:MVVM框架
    Spring Boot入门系列(十七)整合Mybatis,创建自定义mapper 实现多表关联查询!
    Spring Boot入门系列(十六)使用pagehelper实现分页功能
    Spring Boot入门系列(十五)Spring Boot 开发环境热部署
    说迷茫
  • 原文地址:https://www.cnblogs.com/strick/p/5173576.html
Copyright © 2011-2022 走看看