感觉移动端原生支持的 touch、tap、swipe 几个事件好像还不够用,某些时候还会用到诸如缩放、长按等其他功能。

学习了一个手势库 Hammer.js,它是一个轻量级的触屏设备手势库,能识别出常见的触摸、拖动、长按、缩放等行为。 

目录

一、hammer.js简介

二、事件

三、使用方式

四、应用实例


一、hammer.js简介

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

hammerJS很多姿势,比如旋转(Rotate)、捏合(Pinch)、按压(Press)、平移(Pan)、轻触(Tap)、滑动(Swipe)。

二、事件

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:向下滑动

三、使用方式

我非常乖巧,想翻我牌子的话特别简单,new一下即可。

var hammertime = new Hammer(myElement, myOptions);
    hammertime.on('pan', function(ev) {
        console.log(ev);
});

当然也可以玩点更高级的,能同时为您解锁多种姿势

    // get a reference to an element
    var smartisan = document.getElementById('smartisan');

    // create a manager for that element
    var mc = new Hammer.Manager(smartisan);

    // create a recognizer
    var Rotate = new Hammer.Rotate();

    // add the recognizer
    mc.add(Rotate);

    // subscribe to events
    mc.on('rotate', function(e) {
        // do something cool
        var rotation = Math.round(e.rotation);
        stage.style.transform = 'rotate('+rotation+'deg)';
    });

四、应用实例

 对图片进行拖动、缩放和旋转操作(用到hammerJS中的事件Pan、Pinch和Rotate

<!DOCTYPE html>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
		<meta name="format-detection" content="telephone=no">
		<title>Hammer.js-图片拖动、放缩、旋转</title>
		<style>
			html, body {
				margin: 0;
				padding: 0;
				height: 100%;
				min-height: 100%;
				background: #eee;
				font: 13px/1.5em 'Open Sans', Helvetica, Arial, sans-serif;
			}
			a {
				color: #4986e7;
			}
			.bg1, .green { background: #42d692; }
			.bg2, .blue { background: #4986e7; }
			.bg3, .red { background: #d06b64; }
			.bg4, .purple { background: #cd74e6; }
			.bg5, .azure { background: #9fe1e7; }

			body {
				margin: 20px;
			}

			pre {
				background: #fff;
				padding: 20px;
				margin-bottom: 20px;
			}

			.container {
				max-width: 900px;
				margin: 0 auto;
			}

			.clear { clear: both; }
			body { -webkit-perspective: 500; -moz-perspective: 500; perspective: 500; }
			.animate { -webkit-transition: all .3s; -moz-transition: all .3s; transition: all .3s; }
			#hit { padding: 10px; }
			#imgid{width: 300px;}
		</style>
	</head>
	<body>
		<img id="imgid" class="animate" src="images/test2.jpg">
		
		<script type="text/javascript" src="js/hammer.min.js"></script>
		<script>
			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();
		</script>
	</body>
</html>

hammer 中文教程https://www.jianshu/p/0b0b9364f967

在vue 单独使用: https://blog.csdn/weixin_43963309/article/details/119057622

vue 安装插件:vue3-photo-hammer-mixture

更多推荐

Hammer.js - 旋转 拖拽 移动 缩放