H5案例分享:JS手势框架 —— Hammer.js

JS手势框架 —— Hammer.js
一、hammer.js简介
hammerJS是一个开源的,轻量级的触屏设备javascript手势库,它可以在不需要依赖其他东西的情况下识别触摸,鼠标事件。允许同时监听多个手势、自定义识别器,也可以识别滑动方向。
二、事件

1、Rotate事件:在指定的dom区域内,当两个手指或更多手指成圆型旋转时触发(就像两个手指拧螺丝一样)。该事件分别对以下事件进行监听并处理:
Rotatestart:旋转开始;Rotatemove:旋转过程;Rotateend:旋转结束;Rotatecancel:旋转取消
2、Pinch事件:在指定的dom区域内,两个手指(默认为两个手指,多指触控需要单独设置)或多个手指相对(越来越近)移动或相向(越来越远)移动时事件。该事件事以分别对以下事件进行监听并处理:
Pinchstart:多点触控开始;Pinchmove:多点触控过程;Pinchend:多点触控结束;Pinchcancel:多点触控取消;Pinchin:多点触控时两手指距离越来越近;Pinchout:多点触控时两手指距离越来越远
3、Press事件:在指定的dom区域内触屏版本的点击事件,这个事件相当于PC端的Click事件,该不能包含任何的移动,最小按压时间为500毫秒,常用于我们在手机上用的“复制、粘贴”等功能。该事件分别对以下事件进行监听并处理:
Pressup:点击事件离开时触发
4、Pan事件:在指定的dom区域内,一个手指放下并移动事件,即触屏中的拖动事件。这个事件在屏触开发中比较常用,如:左拖动、右拖动等,如手要上使用QQ时向右滑动出现功能菜单的效果。该事件还可以分别对以下事件进行监听并处理:
Panstart:拖动开始;Panmove:拖动过程;Panend:拖动结束;Pancancel:拖动取消;Panleft:向左拖动;Panright:向右拖动;Panup:向上拖动;Pandown:向下拖动
5、Tap事件:在指定的dom区域内,一个手指轻拍或点击时触发该事件(类似PC端的click)。该事件最大点击时间为250毫秒,如果超过250毫秒则按Press事件进行处理。
6、Swipe事件:在指定的dom区域内,一个手指快速的在触屏上滑动。即我们平时用到最多的滑动事件。
Swipeleft:向左滑动;Swiperight:向右滑动;Swipeup:向上滑动;Swipedown:向下滑动
三、使用方式
//创建一个新的hammer对象并且在初始化时指定要处理的dom元素
var hammertime = new Hammer(document.getElementById("test"));
//为该dom元素指定触屏移动事件
hammertime.on("pan", function (ev) {
//控制台输出
console.log(ev);
});
四、应用实例
对图片进行拖动、缩放和旋转操作(用到hammerJS中的事件Pan、Pinch和Rotate)
核心代码:
var reqAnimationFrame = (function () {
return window[Hammer.prefixed(window, 'requestAnimationFrame')] || function (callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
var el = document.querySelector("#imgid");
var START_X = Math.round((window.innerWidth - el.offsetWidth) / 2);
var START_Y = Math.round((window.innerHeight - el.offsetHeight) / 2);
var ticking = false;
var transform; //图像效果
var timer;
var initAngle = 0; //旋转角度
var initScale = 1; //放大倍数
var mc = new Hammer.Manager(el); //用管理器 可以同时触发旋转 拖拽 移动
//var mc = new Hammer(el); //旋转和移动互斥
/**
ev.srcEvent.type touchstart touchend touchmove
ev.deltaX 手势移动位移变量
*/
mc.add(new Hammer.Pan({ threshold: 0, pointers: 0 }));
mc.add(new Hammer.Rotate({ threshold: 0 })).recognizeWith(mc.get('pan'));
mc.add(new Hammer.Pinch({ threshold: 0 })).recognizeWith([mc.get('pan'), mc.get('rotate')]);
//结束时做一些处理
mc.on("hammer.input", function(ev) {
if(ev.isFinal) {
console.log(START_X+" "+transform.translate.x +" "+ev.deltaX);
START_X = transform.translate.x ;
START_Y = transform.translate.y ;
}
});
mc.on("panstart panmove", onPan);
mc.on("rotatestart rotatemove rotateend", onRotate);
mc.on("pinchstart pinchmove", onPinch);
/**
第二次进入拖拽时 delta位移重置
移动时 初始位置startxy不动。delta增加
*/
function onPan(ev){
if(!ev.isFinal) {
el.className = '';
console.log(START_X +" "+ START_Y +" | "+ev.deltaX +" "+ ev.deltaY);
transform.translate = {
x: START_X + ev.deltaX,
y: START_Y + ev.deltaY
};
requestElementUpdate();
}
}
function onPinch(ev){
if(ev.type == 'pinchstart') {
initScale = transform.scale || 1;
}
el.className = '';
transform.scale = initScale * ev.scale;
requestElementUpdate();
}
//旋转相关
var preAngle =0 ;
var tempAngleFlag=0;
var deltaAngle = 0;
var startRotateAngle = 0;
function onRotate(ev) {
//点下第二个触控点时触发
if(ev.type == 'rotatestart') {
startRotateAngle = ev.rotation ;
tempAngleFlag = 0 ;
}
if(ev.type == 'rotatemove'){
if(tempAngleFlag == 0){
preAngle = startRotateAngle;
tempAngleFlag ++;
}else{
deltaAngle = ev.rotation - preAngle;
el.className = '';
transform.rz = 1; //非0 垂直xy轴
transform.angle =initAngle + deltaAngle;
requestElementUpdate();
}
}
//旋转结束 记录当前图片角度
if(ev.type =='rotateend'){
initAngle = transform.angle;
}
}
function updateElementTransform() {
var value = [
'translate3d(' + transform.translate.x + 'px, ' + transform.translate.y + 'px, 0)',
'scale(' + transform.scale + ', ' + transform.scale + ')',
'rotate3d('+ transform.rx +','+ transform.ry +','+ transform.rz +','+ transform.angle + 'deg)'
];
value = value.join(" ");
el.style.webkitTransform = value; /*为Chrome/Safari*/
el.style.mozTransform = value; /*为Firefox*/
el.style.transform = value; /*IE Opera?*/
ticking = false;
}
function requestElementUpdate() {
if(!ticking) {
reqAnimationFrame(updateElementTransform);
ticking = true;
}
}
/**
初始化设置
*/
function resetElement() {
el.className = 'animate';
transform = {
translate: { x: START_X, y: START_Y },
scale: 1,
angle: 0,
rx: 0,
ry: 0,
rz: 0
};
requestElementUpdate();
}
resetElement();
DEMO演示

五、注意事项
- 试着避免垂直方向上的 pan/swipe
垂直方向上的平移操作一般是用来滚动页面的,而且有些(过时的)浏览器不会传递事件,导致Hammer无法识别这些手势。
- 在设备上做测试
有时候Hammer需要做一些调整,像swipe的速率或其它阈值,如果你在一台反应较慢的设备上做测试,那么你要保证你的回调越简单越好。
- 去掉Windows Phone点击时的高亮效果
在Windows Phone上的IE10和IE11里tap某元素时,会有一个小小的tap高亮效果,加上这个meta标签可以取消这种效果:
- 选择不了文本
Hammer设置了一个属性用来提升桌面平移操作的用户体验(UX)。常规来说,当你在桌面级浏览器上拖动页面时,你应该是可以正常选中文本的,但user-select这个CSS属性禁用了这功能。如果你在意文本选择功能,同时觉得桌面级的体验没必要太尽善尽美,你可以很轻松地取消这个默认选项——确保在创建实例之前执行:
delete Hammer.defaults.cssProps.userSelect;
5.在tap之后,导致触发了一个click事件
这种click事件我们称之为一个“幽灵点击”事件,可创建了一个小函数来避免触摸后导致click。
六、浏览器/终端的支持
Harmmer可以运行在除了IE8及其以下的任何浏览器。浏览器若对触摸行为(touch-action)提供原生支持,那么对比那些不支持HarmmerJS某些事件的浏览器,将会有更好的体验。

H5案例分享:JS手势框架 —— Hammer.js的更多相关文章
- 移动端手势库Hammer.js学习
感觉移动端原生支持的 touch.tap.swipe 几个事件好像还不够用,某些时候还会用到诸如缩放.长按等其他功能. 近日学习了一个手势库 Hammer.js,它是一个轻量级的触屏设备手势库,能识别 ...
- H5案例分享:使用JS判断客户端、浏览器、操作系统类型
使用JS判断客户端.浏览器.操作系统类型 一.JS判断客户端类型 JS判断客户端是否是iOS或者Android手机移动端 通过判断浏览器的userAgent,用正则来判断手机是否是ios和Androi ...
- 移动端手势事件 hammer.JS插件
一.引入hammer.JS 1.下载地址:http://download.csdn.net/detail/webxiaoma/9872249 2.官网地址:http ...
- 强大的 Node.js Web 框架 - Daze.js
去年年初对 Node.js 比较感兴趣,也用了很多 Node.js 的框架,但是开发体验不是特别好,我之前也是后端转前端,然后再接触 Node.js ,所以用过挺多的服务端框架,相对js而言,设计一款 ...
- H5案例分享:移动端touch事件判断滑屏手势的方向
移动端touch事件判断滑屏手势的方向 方法一 当开始一个touchstart事件的时候,获取此刻手指的横坐标startX和纵坐标startY: 当触发touchmove事件时,在获取此时手指的横坐标 ...
- H5案例分享:移动端滑屏 touch事件
移动端滑屏 touch事件 移动端触屏滑动的效果的效果在电子设备上已经被应用的越来越广泛,类似于PC端的图片轮播,但是在移动设备上,要实现这种轮播的效果,就需要用到核心的touch事件.处理touch ...
- H5案例分享:html5移动开发细微之美
html5移动开发细微之美 1.H5页面窗口自动调整到设备宽度,并禁止用户缩放页面 <meta name="viewport" content="width=dev ...
- H5案例分享:html5重力感应事件
html5重力感应事件 一.手机重力感应图形分析 1.设备围绕z轴的旋转角度为α,α角度的取值范围在[0,360). 设备在初始位置,与地球(XYZ)和身体(XYZ)某个位置对齐. 设备围绕z轴的旋转 ...
- Hammer.js移动端触屏框架的使用
hammer.js是一个多点触摸手势库,能够为网页加入Tap.Double Tap.Swipe.Hold.Pinch.Drag等多点触摸事件,免去自己监听底层touchstart.touchmove. ...
随机推荐
- jQuery获取margin-top和padding-top的值
var bordT = $('img').outerWidth() - $('img').innerWidth(); var paddT = $('img').innerWidth() - $('i ...
- jQuery Ajax 实例 ($.ajax、$.post、$.get)
jQuery Ajax 实例 ($.ajax.$.post.$.get) 转 Jquery在异步提交方面封装的很好,直接用AJAX非常麻烦,Jquery大大简化了我们的操作,不用考虑浏览器的诧异了. ...
- C# 7.0 新功能代码范例
随着新版本的IDE Visual Studio 15 紧锣密鼓的开发中,2016年8月24日,微软发布了与之配套的C# 7.0 preview 的新特性. 其主要特性有: 内联声明out变量 (Out ...
- Docker的安装
目前Docker可以在Linux系统.Windows系统,这个文档介绍3种安装方式,安装Docker版本为1.8.2 具备安装Docker的条件: 64位CPU架构的设备 Linux系统内核推荐3.1 ...
- Android 提醒公共方法 Notification
SimpAndroidFarme是近期脑子突然发热想做的android快速开发的框架,目标是模块化 常用的控件,方便新手学习和使用.也欢迎老鸟来一起充实项目:项目地址 今天的目标是做一个公共的提醒方法 ...
- python学习之路 第二天
1.import 导入模块 #!/usr/bin/python # -*- coding:utf-8 -*- import sys print(sys.argv) 2.字符串常用方法: 移除空白: s ...
- 从PHP底层源码去深入理解数组,并用C模拟PHP关联数组(原创)
PHP是一门入门容易,使用范围广泛的语言,以其灵活性以及web后端开发被很多人熟知,也被很多人戏称“PHP是世界上最好的语言”.本人是一名“忠实”的PHPer,相信用过PHP的程序员都会体会到PHP数 ...
- xss篇-本着就了解安全本质的想法,尽可能的用通俗易懂的语言去解释安全漏洞问题
前言 最早接触安全也是从xss攻击和sql注入攻击开始的. 0x01 跨站脚本攻击漏洞(XSS),是客户端脚本安全中的头号大敌,owasp top10 屡居榜首,由于攻击手法较多,开发者水平不一 ...
- bzoj1500
1500: [NOI2005]维修数列 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 12544 Solved: 3970[Submit][Statu ...
- 一个解析json串并组装echarts的option的函数解析
缘起: 在组装echart页面的时候,遇到这样一个问题,它是一个需要在循环内层的时候,同时循环外层,在内层循环中就要将外层获取的值存入,导致了一种纠缠状态,费了老劲儿,终于得到如下解决.记录之,绿色为 ...