
感觉移动端原生支持的 touch、tap、swipe 几个事件好像还不够用,某些时候还会用到诸如缩放、长按等其他功能。
学习了一个手势库 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)
- 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.com/p/0b0b9364f967
在vue 单独使用: https://blog.csdn.net/weixin_43963309/article/details/119057622
vue 安装插件:vue3-photo-hammer-mixture