浏览器底层并没有给元素提供类似,单击,双击,滑动,拖动这些直接可以用的控制接口,一切的手势动作都只能通过模拟出来。移动端浏览器唯一给我们提供的就只是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. JavaScript如何获取网页url中的参数

    我们可以自定义一个公共函数来实现网页url中的参数获取,返回的是一个数组 GetUrlRequest: function () { var url = decodeURI(location.searc ...

  2. QPalette的用法

    1.QPalette的概念 调色板类QPallete提供了颜色角色(color roles)概念,是指当前GUI界面中颜色的职责,通过枚举变量QPalette::ColorRole来定义, 比较常用的 ...

  3. java nio系列文章

    java nio系列教程 基于NIO的Client/Server程序实践 (推荐) java nio与并发编程相关电子书籍   (访问密码 48dd) 理解NIO nio学习记录 图解ByteBuff ...

  4. Windows批处理:自动部署常用软件(静默安装)

    一.简介 最近一直在测试使用域组策略自动部署软件,效果并不理想.首先,主机必须加入域才能让策略生效.其实是Windows Server 2012 R2只支持.msi格式的安装包,所以部署前需将软件重新 ...

  5. (转)Dubbo与Zookeeper、SpringMVC整合和使用

    原文地址: https://my.oschina.net/zhengweishan/blog/693163 Dubbo与Zookeeper.SpringMVC整合和使用 osc码云托管地址:http: ...

  6. AJAX提交方法(POST)Demon

    AJAX的POST提交方法,本质上来看和GET差不多,有些细小的区别,POST要提交数据时,需要setRequestHeader()方法来提交HTTP头,然后send()方法中提交数据(格式为:&qu ...

  7. [LeetCode] Nested List Weight Sum II 嵌套链表权重和之二

    Given a nested list of integers, return the sum of all integers in the list weighted by their depth. ...

  8. [LeetCode] Game of Life 生命游戏

    According to the Wikipedia's article: "The Game of Life, also known simply as Life, is a cellul ...

  9. 滑动验证的设计与实现J2EE

    滑动验证的设计与实现J2EE 注:本博文为博主原创,转载请注明出处. 项目源码地址:https://github.com/zhangxy1035/Verify 本篇博文的主要目录如下: 一.项目简介二 ...

  10. 安装cocoapods

    1. 看一下ruby的版本 ruby -v 2. 删除默认源 gem sources --remove https://rubygems.org/ 3. 添加淘宝源 gem sources -a ht ...