移动开发框架剖析(二) Hammer专业的手势控制
浏览器底层并没有给元素提供类似,单击,双击,滑动,拖动这些直接可以用的控制接口,一切的手势动作都只能通过模拟出来。移动端浏览器唯一给我们提供的就只是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);
每一个识别器各自处理其行为了,当然这里面倒是如何触发,手势识别器如何判断是那种手势,就放一章了。
我的:https://github.com/JsAaron/hammer-js
移动开发框架剖析(二) Hammer专业的手势控制的更多相关文章
- 移动开发框架剖析(一) Hammer专业的手势控制
一直在写jQuery的源码教程,都没时间研究别的框架了.Hammer是我项目御用的一个手势库,早期1.x版本的swipe事件的响应不灵敏的问题而改过源码,2.x就已经更正过来,而且源码的结构也整个翻新 ...
- Prism for WPF 搭建一个简单的模块化开发框架(二)
原文:Prism for WPF 搭建一个简单的模块化开发框架(二) 今天又有时间了,再改改,加了一些控件全局的样式 样式代码 <ResourceDictionary xmlns="h ...
- libevent源码深度剖析二
libevent源码深度剖析二 ——Reactor模式 张亮 前面讲到,整个libevent本身就是一个Reactor,因此本节将专门对Reactor模式进行必要的介绍,并列出libevnet中的几个 ...
- Swift实战-豆瓣电台(九)简单手势控制暂停播放(全文完)
Swift实战-豆瓣电台(九)简单手势控制暂停播放 全屏清晰观看地址:http://www.tudou.com/programs/view/tANnovvxR8U/ 这节我们主要讲UITapGestu ...
- Unity3D中使用Leap Motion进行手势控制
Leap Motion作为一款手势识别设备,相比于Kniect,长处在于准确度. 在我的毕业设计<场景漫游器>的开发中.Leap Motion的手势控制作为重要的一个环节.以此,谈谈开发中 ...
- C#基础课程之二变量常量及流程控制
课堂练习:.一个四位整数 输出它的千位,百位,十位,个位 数字. ; ; % ; % ; ; Console.WriteLine("千位数" + b+" 百位数" ...
- MIT 黑科技:通过脑电波和手势控制机器人
简评:麻省理工黑科技,虽然现在能实现的操作还很简单,但前景(想象空间)非常巨大. 通常,控制机器人并不容易,常规手段就是编程.但是地球上从来不缺天马行空的科学家,今日 MIT 的计算机科学与人工智能实 ...
- Azure Service Bus(二)在NET Core 控制台中如何操作 Service Bus Queue
一,引言 上一篇讲到关于 Azure ServiceBus 的一些概念,讲到 Azure Service Bus(服务总线),其实也叫 "云消息服务",是微软在Azure 上提供的 ...
- Solon Web 开发,十二、统一的渲染控制
Solon Web 开发 一.开始 二.开发知识准备 三.打包与运行 四.请求上下文 五.数据访问.事务与缓存应用 六.过滤器.处理.拦截器 七.视图模板与Mvc注解 八.校验.及定制与扩展 九.跨域 ...
随机推荐
- SqlServer SET IDENTITY_INSERT ON | OFF
想要将值插入到自动编号(或者说是标识列,IDENTITY)中去,需要设定 SET IDENTITY_INSERT 示例: 1.首先建立一个有标识列的表: )) 2.尝试在表中做以下操作: , 'gar ...
- [转]C# 使用Nlog记录日志到数据库
本文转自:http://www.cnblogs.com/weixing/archive/2013/04/26/3044422.html 摘要]Nlog是一个很不错的.NET日志记录组件,它可以将日志输 ...
- Hanoi问题java解法
用什么语言解法都差不多,思路都是一样,递归,这其中只要注重于开始和结果的状态就可以了,对于中间过程,并不需要深究.(我细细思考了一下,还是算了.=_=) 代码其实很简单注重的是思路. 问题描述:有一个 ...
- 记一次从邻居无线路由渗透到邻居PC
起因:因为房东的网太垃圾 决定自己动手丰衣足食蹭邻居的网 结果发现一个信号超好的无线路由0x01踩点 无意中发现TP-LINK_28C0这个无线信号特别的好 看起来就肯定知道是隔壁邻居的 抓了一下包 ...
- 用js实现动画效果核心方式
为了做好导航菜单,有时候需要在菜单下拉的时候实现动画效果,所以这几天就研究了研究如何用js实现动画效果,实现动画核心要用到两个函数,一个是setTimeOut,另一个是setInterval. 下边我 ...
- ActiveMQ笔记(6):消息延时投递
在开发业务系统时,某些业务场景需要消息定时发送或延时发送(类似:飞信的短信定时发送需求),这时候就需要用到activemq的消息延时投递,详细的文档可参考官网说明,本文只介绍二种常用的用法: 注:本文 ...
- 当AngularJS POST方法碰上PHP
问题描述 怎么POST过去给PHP都收不到资料? $_POST方法取不到正确的传入值! 原理说明 AngularJS这套framework使用的AJAX方法中,资料传递的格式为JSON,送出去的hea ...
- Spring + SpringMVC + Druid + MyBatis 给你一个灵活的后端解决方案
生命不息,折腾不止. 折腾能遇到很多坑,填坑我理解为成长. 两个月前自己倒腾了一套用开源框架构建的 JavaWeb 后端解决方案. Spring + SpringMVC + Druid + JPA(H ...
- REDIS持久化报错失败
redis log报错: [7666] 15 Jan 00:22:36.028 # Error moving temp DB file on the final destination: Invali ...
- vs2013中2.0类库提示是英文,解决方案
将C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\zh-Hans下的XML文件复 ...