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

简介: 从github上面将源码下载下来,会发现有个src文件夹。当前版本是2.0.6。

github上面将源码下载下来,会发现有个src文件夹。当前版本是2.0.6。


25.jpg总的结构如下:


26.jpg


一、常量


这里将常量全部列在一起是可以在对比源码的时候,更方便的查看相应内容。


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”处,上下滑动,屏幕不会跟着滚动。


26.jpg


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

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

27.jpg


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();
});


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

28.jpg


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

 

相关文章
|
18天前
|
Web App开发 监控 JavaScript
监控和分析 JavaScript 内存使用情况
【10月更文挑战第30天】通过使用上述的浏览器开发者工具、性能分析工具和内存泄漏检测工具,可以有效地监控和分析JavaScript内存使用情况,及时发现和解决内存泄漏、过度内存消耗等问题,从而提高JavaScript应用程序的性能和稳定性。在实际开发中,可以根据具体的需求和场景选择合适的工具和方法来进行内存监控和分析。
|
8天前
|
JavaScript 前端开发 API
Vue.js与Angular的优劣分析
Vue.js和Angular都是非常流行的JavaScript框架,它们在构建现代Web应用程序方面各有优劣
|
14天前
|
运维 监控 JavaScript
鸿蒙next版开发:分析JS Crash(进程崩溃)
在HarmonyOS 5.0中,JS Crash指未处理的JavaScript异常导致应用意外退出。本文详细介绍如何分析JS Crash,包括异常捕获、日志分析和典型案例,帮助开发者定位问题、修复错误,提升应用稳定性。通过DevEco Studio收集日志,结合HiChecker工具,有效解决JS Crash问题。
35 4
|
23天前
|
Web App开发 JavaScript 前端开发
使用 Chrome 浏览器的内存分析工具来检测 JavaScript 中的内存泄漏
【10月更文挑战第25天】利用 Chrome 浏览器的内存分析工具,可以较为准确地检测 JavaScript 中的内存泄漏问题,并帮助我们找出潜在的泄漏点,以便采取相应的解决措施。
140 9
|
21天前
|
JavaScript 前端开发 开发者
前端框架对比:Vue.js与Angular的优劣分析与选择建议
【10月更文挑战第27天】在前端开发领域,Vue.js和Angular是两个备受瞩目的框架。本文对比了两者的优劣,Vue.js以轻量级和易上手著称,适合快速开发小型到中型项目;Angular则由Google支持,功能全面,适合大型企业级应用。选择时需考虑项目需求、团队熟悉度和长期维护等因素。
30 1
|
22天前
|
JavaScript 前端开发 API
前端框架对比:Vue.js与Angular的优劣分析与选择建议
【10月更文挑战第26天】前端技术的飞速发展让开发者在构建用户界面时有了更多选择。本文对比了Vue.js和Angular两大框架,介绍了它们的特点和优劣,并给出了在实际项目中如何选择的建议。Vue.js轻量级、易上手,适合小型项目;Angular结构化、功能强大,适合大型项目。
19 1
|
1月前
|
数据采集 JSON 前端开发
JavaScript逆向爬虫实战分析
JavaScript逆向爬虫实战分析
|
5月前
|
Web App开发 前端开发 JavaScript
技术心得记录:瀑布流的布局原理分析(纯CSS瀑布流与JS瀑布流)
技术心得记录:瀑布流的布局原理分析(纯CSS瀑布流与JS瀑布流)
59 0
|
1月前
|
前端开发 JavaScript
JavaScript动态渲染页面爬取——CSS位置偏移反爬案例分析与爬取实战
JavaScript动态渲染页面爬取——CSS位置偏移反爬案例分析与爬取实战
|
5月前
|
JavaScript 前端开发 算法
虚拟DOM是React的关键技术,它是个轻量的JS对象树,模拟实际DOM结构。
【6月更文挑战第27天】虚拟DOM是React的关键技术,它是个轻量的JS对象树,模拟实际DOM结构。当状态改变,React不直接修改DOM,而是先构建新的虚拟DOM树。通过 diff 算法比较新旧树,找到最小变更,仅更新必要部分,提高性能,避免频繁DOM操作。虚拟DOM还支持跨平台应用,如React Native。它优化了更新流程,简化开发,并提升了用户体验。
44 1
下一篇
无影云桌面