浏览器底层并没有给元素提供类似,单击,双击,滑动,拖动这些直接可以用的控制接口,一切的手势动作都只能通过模拟出来。移动端浏览器唯一给我们提供的就只是mousedown -> mousemove -> mouseup三种最基本的事件接口。那么我们只能通过这些简单的接口模拟出复杂的手势出来。

常规的做法流程:

1.给元素上绑定三个事件,mousedown ,mousemove,mouseup

2.在交互的时候,用户只触发mousedown,mouseup没有触发mousemove,就可以单算是一次点击的动作, 这里可以是 单击,双击与长按,具体可以通过间隔的时间判断

3.如果mousemove触发了,自然就是滑动与拖动了

当然手势还要涉及到多点操作缩放与旋转的处理,就之后在讨论。


先抛开流程,我们要知道设计一个手势库需要考虑的问题,至少有2点:

1.运行的平台

2.用户的手势

那么我们可以总结市面上的终端设备有那么三种:

1 手机/pad移动端

2 pc类

3 还有种带触摸屏的电脑一类

用户的手势行为大体分:

单击tap , 双击doubletap,平移pan,滑动swipe,长按press,缩放pinch,旋转rotate


从设计的角度来讲,有着不同的兼容与选择问题,却又有着一些相同的共性与处理我们要如何去组织结构?

当然依旧是OOP设计了,抽出父类,实现继承,引入策略模式

我们看看Hammer在结构上是如何实现这类设计的

常规来说手势的处理,要分为初始化与执行期。初始化的时候构建所有相关的参与与方法

hammer源码里面分几大块:

1. Hammer类,一个简单的工厂方法,用来创建一个管理和初始化默认的识别器。Hammer.defaults配置一些基本的选项

包括针对每种识别器的配置与元素CSS属性的设置

2. Manager类,整个库的管理类。内部初始化了input输入对象,所有手势对象,元素css设置对象touchAction

3. InputHandler类,事件回调的具体加工类,用来生成包装后的事件对象与派发事件到每一个识别器

4. TouchAction类,设置元素的touchAction属性

5. Input类,事件处理类。用来处理绑定与销毁,事件句柄的回调。每一个输入类都需要继承

6. Recognizer类,所有识别器需要继承的基类

以上就是整个库的类块了,当然5与6都是属于基类继承的,在代码运行的时候就自动构建完毕了


关于继承inherit方法

hammer用的是传统的类似继承

function inherit(child, base, properties) {
var baseP = base.prototype,
childP; childP = child.prototype = Object.create(baseP);
childP.constructor = child;
childP._super = baseP; if (properties) {
extend(childP, properties);
}
}

只继承了原型的方法,因为原型都是共享的,如果放置属性可以被任何一个继承的子类所有修改,所以属性的继承需要用call方法

继承的子类有一个私有属性 _super指向父类,同时还能额外的扩展方法

inherit(MouseInput, Input, {
handler: function MEhandler(ev){
}
}

子类MouseInput继承父类Input类的所有原型方法,并扩展了handler方法


输入设备初始化继承:就是通过什么设备触发动作(PC,手机,ipad等等)

输入设备hammer分为

MouseInput,PointerEventInput,SingleTouchInput,TouchInput,TouchMouseInput

我们看看最简单的桌面PC的鼠标输入处理MouseInput,其余的结构基本类似。

function MouseInput() {
this.evEl = MOUSE_ELEMENT_EVENTS;
this.evWin = MOUSE_WINDOW_EVENTS;
//用来禁止TouchMouse事件
this.allow = true; // used by Input.TouchMouse to disable mouse events
//鼠标按下的状态
this.pressed = false; // mousedown state
Input.apply(this, arguments);
} inherit(MouseInput, Input, {
handler: function MEhandler(ev){
..//////////////
}
}

MouseInput初始化了几个必要的判断属性,然后就只handler方法, 此外还集成了Input输入类

比如我们调用

new MouseInput(callback)的时候,通过Input.apply(this, arguments)去初始化了基类input类,然后基类内部的init绑定了事件,并且把事件的回调,

this.domHandler指向了外部的callback回调,其实也就是handler方法了

addEventListeners(this.element, this.evEl, this.domHandler);

另一个基类就是Recognizer

因为我们把用户的行为分为单击tap , 双击doubletap,平移pan,滑动swipe,长按press,缩放pinch,旋转rotate,那么类似相同点我们也必须抽象成一个基类

Recognizer比如复杂,留在执行期的时候讲解。


Hammer 使用:

var mc = new Hammer(el);

那么内部的构建

function Hammer(element, options) {
options = options || {};
//配置手势识别器参数
options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset);
return new Manager(element, options);
}

可见最终是Manager构建的对象实例了

Manager内部,通过createInputInstance创建一个输入环境的实例对象,创建一个输入环境的实例对象

this.input = createInputInstance(this);

createInputInstance的作用主要是用来选择当然的平台,不同的平台会调用不同的手势输入处理,这里就有策略选择了的处理了

function createInputInstance(manager) {
var Type;
var inputClass = manager.options.inputClass; if (inputClass) {
Type = inputClass;
} else if (SUPPORT_POINTER_EVENTS) {
Type = PointerEventInput;
} else if (SUPPORT_ONLY_TOUCH) {
Type = TouchInput; //移动手机端
} else if (!SUPPORT_TOUCH) {
Type = MouseInput; //桌面
} else {
Type = TouchMouseInput;
}
}

如果是桌面PC端,我们就会走MouseInput

return new MouseInput(manager, inputHandler);

这样把具体的通过Input类绑定的回调放到MouseInput的handler处理了,最终的回调会进入总处理inputHandler类

inputHandler类就会遍历所有的手势识别器把输入的input传入

manager.recognize(input);

每一个识别器各自处理其行为了,当然这里面倒是如何触发,手势识别器如何判断是那种手势,就放一章了。

官方:http://hammerjs.github.io/

我的:https://github.com/JsAaron/hammer-js

移动开发框架剖析(二) Hammer专业的手势控制的更多相关文章

  1. 移动开发框架剖析(一) Hammer专业的手势控制

    一直在写jQuery的源码教程,都没时间研究别的框架了.Hammer是我项目御用的一个手势库,早期1.x版本的swipe事件的响应不灵敏的问题而改过源码,2.x就已经更正过来,而且源码的结构也整个翻新 ...

  2. Prism for WPF 搭建一个简单的模块化开发框架(二)

    原文:Prism for WPF 搭建一个简单的模块化开发框架(二) 今天又有时间了,再改改,加了一些控件全局的样式 样式代码 <ResourceDictionary xmlns="h ...

  3. libevent源码深度剖析二

    libevent源码深度剖析二 ——Reactor模式 张亮 前面讲到,整个libevent本身就是一个Reactor,因此本节将专门对Reactor模式进行必要的介绍,并列出libevnet中的几个 ...

  4. Swift实战-豆瓣电台(九)简单手势控制暂停播放(全文完)

    Swift实战-豆瓣电台(九)简单手势控制暂停播放 全屏清晰观看地址:http://www.tudou.com/programs/view/tANnovvxR8U/ 这节我们主要讲UITapGestu ...

  5. Unity3D中使用Leap Motion进行手势控制

    Leap Motion作为一款手势识别设备,相比于Kniect,长处在于准确度. 在我的毕业设计<场景漫游器>的开发中.Leap Motion的手势控制作为重要的一个环节.以此,谈谈开发中 ...

  6. C#基础课程之二变量常量及流程控制

    课堂练习:.一个四位整数 输出它的千位,百位,十位,个位 数字. ; ; % ; % ; ; Console.WriteLine("千位数" + b+" 百位数" ...

  7. MIT 黑科技:通过脑电波和手势控制机器人

    简评:麻省理工黑科技,虽然现在能实现的操作还很简单,但前景(想象空间)非常巨大. 通常,控制机器人并不容易,常规手段就是编程.但是地球上从来不缺天马行空的科学家,今日 MIT 的计算机科学与人工智能实 ...

  8. Azure Service Bus(二)在NET Core 控制台中如何操作 Service Bus Queue

    一,引言 上一篇讲到关于 Azure ServiceBus 的一些概念,讲到 Azure Service Bus(服务总线),其实也叫 "云消息服务",是微软在Azure 上提供的 ...

  9. Solon Web 开发,十二、统一的渲染控制

    Solon Web 开发 一.开始 二.开发知识准备 三.打包与运行 四.请求上下文 五.数据访问.事务与缓存应用 六.过滤器.处理.拦截器 七.视图模板与Mvc注解 八.校验.及定制与扩展 九.跨域 ...

随机推荐

  1. Newtonsoft.Json, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b9a188c8922137c6

    未能加载文件或程序集“Newtonsoft.Json, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b9a188c8922137c6”或它的某一个 ...

  2. mongodb高级应用

    一.  高级查询 查询操作符 条件操作符:db.collection.find({"field":{$gt/$lt/$gte/$lte/$eq/$ne:value}}); 匹配所有 ...

  3. 数据库Sharding系列文章

    关于数据库Sharding的策略,有人整理出相关的方案,看完收获很大. 数据库分库分表(sharding)系列(五) 一种支持自由规划无须数据迁移和修改路由代码的Sharding扩容方案 数据库分库分 ...

  4. ubuntu安装pppoeconf后与networkmanager冲突

    使用pppoeconf拨号后,Network Manager显示设备未托管的解决办法: 在终端中输入以下命令,来配置网络连接管理文件: sudo gedit /etc/NetworkManager/n ...

  5. hibernate学习-HibernateDemo

    上篇文章我们讲述了eclipse安装hibernate插件的过程,这篇文章我们来做第一个HibernateDemo. 1).hibernate的jar开发包的下载,官网下载地址:http://hibe ...

  6. [No000098]SVN学习笔记5-分支,合并,属性,补丁,锁,分支图

    行结束符和空白选项 在项目的生命周期中,有时可能会将行结束符由 CRLF 改为 LF,或者修改一段代码的缩进.不幸的是这样将会使大量的代码行被标记为已修改,尽管代码本身并没有被修改.这里列出的选项将会 ...

  7. 如何给SVG填充和描边应用线性渐变

    给SVG元素应用填充和描边有三种方法(戳这里学习SVG填充和描边的相关内容).你可以使用纯色.图案或渐变.前面两种方法我们之前已经讲过了,现在我们来讨论第三种方法——渐变. SVG提供了两种渐变——线 ...

  8. 【深度学习Deep Learning】资料大全

    最近在学深度学习相关的东西,在网上搜集到了一些不错的资料,现在汇总一下: Free Online Books  by Yoshua Bengio, Ian Goodfellow and Aaron C ...

  9. 函数:MySQL中字符串匹配函数LOCATE和POSITION使用方法

    1. 用法一 LOCATE(substr,str) POSITION(substr IN str) 函数返回子串substr在字符串str中第一次出现的位置.如果子串substr在str中不存在,返回 ...

  10. php设计模式--面向对象

    php链式操作的实现: 特点:1.链式操作一般存在于面向对象的情况下链式操作才有意义 /* * SQL语句组合实例类,始发文章web开发笔记 * 学习用,非专业类 * */ class sql{ pr ...