Javascript 常用手势, 个人觉得有3个 tap,swipe(swipeLeft,swipeRight,swipeTop,swipeRight),hold
tap 是轻击 判断的原则是,在toustart后,移动范围不超过10px(圆的范围),就算是 轻击了
swipe 是轻滑(轻扫) 判断在toustart后,时间间隔小于300ms,移动范围大于20,就判断是轻滑
hold(常按) 按住 移动范围小于10px,时间大于200ms,就认为他是hold
自定义手势,网上相关的源码很多,我也找了一个来研究,叫touch.js,挺不错的支持pc端,移动端(移动端就是touchstart,pc端就是mousedown),虽然有些小bug,比如事件删除有问题
touch.js的地址 http://touch.code.baidu.com/
一些要准备的基础
手势的基本实现原理
阉割源码解析
支持移动端 pc端的阉割源码解析
zepto的手势源码解析
一些我遇到的手势问题
1.对touch相关的东西要了解
指尖上的js是很好的东西呀
指尖上的js一
指尖上的js二
指尖上的js三
2.自定义事件CustomEvent
dom是添加自定义事件的,也可以触发它,它还以冒泡
火狐的一个官方说明 官方说明
一篇比较详细的介绍,还有例子点点点
自定义事件是可以用Chrome看到的,如图
tap,hold,swipe都是js没有的事件,都是由,touchstart,touchmove,touchend touchcancel这些事件组合而成的
实现原理就是通过绑定document的”touchstart touchmove touchend touchcancel“事件
当touch到元素,查看手势是否符合tap,swipe的原则
如果符合原则,就触发元素绑定的相关事件
判断移动了多少位置
比如我点击了元素a,我就就得记下点击时的位置,计算方式如下
touches[0].pageX,touches[0].pageY
这个是手指点击的位置离页面顶端的位置(或者是页面的左边)
然后再touchmove时记下相关的位置
在touchend或者touchcancel时,用2个数据,算一下移动了多少就行了
ps:touchend和touchcancel是没有event的所以必须在touchmove里面记录位置
touch.js 以我的水平来看,并不能很流畅的阅读源码...
而且有些手势也不是很常用,做了些阉割,写了些注释,方便理解
<html><head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> <title>wo ca!~</title> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <meta name="format-detection" content="telephone=no"></head><style> .xx{width: 200px;background: #ccc; height: 100px;}</style><body><div id="vv" class="xx"></div><br><div id="ss" class="xx"></div><br><div id="ss1" class="xx">1</div><br><div id="ss2" class="xx">1</div><br><div id="ss3" class="xx"></div><br><div id="ss4" class="xx"></div><script> (function(){ var utils = {}; //获取元素的点击位置 utils.getPosOfEvent = function(ev){ var posi = []; var src = null; for (var t = 0, len = ev.touches.length; t < len; t++) { src = ev.touches[t]; posi.push({ x: src.pageX, y: src.pageY }); } return posi; } utils.getType = function(obj) { return Object.PRototype.toString.call(obj).match(//s([a-z|A-Z]+)/)[1].toLowerCase(); }; //获取点击的手指数量 utils.getFingers = function(ev) { return ev.touches ? ev.touches.length : 1; }; utils.isTouchMove = function(ev) { return ev.type === 'touchmove'; }; //是否已经结束了手势 utils.isTouchEnd = function(ev) { return (ev.type === 'touchend' || ev.type === 'touchcancel'); }; //算2点之间的距离 utils.getDistance = function(pos1, pos2) { var x = pos2.x - pos1.x, y = pos2.y - pos1.y; return Math.sqrt((x * x) + (y * y)); }; //算角度 utils.getAngle = function(p1, p2) { return Math.atan2(p2.y - p1.y, p2.x - p1.x) * 180 / Math.PI; }; //根据角度 返回up down left right utils.getDirectionFromAngle = function(agl) { var directions = { up: agl < -45 && agl > -135, down: agl >= 45 && agl < 135, left: agl >= 135 || agl <= -135, right: agl >= -45 && agl <= 45 }; for (var key in directions) { if (directions[key]) return key; } return null; }; utils.reset = function() { startEvent = moveEvent = endEvent = null; __tapped = __touchStart = startSwiping = false; pos = {start: null,move: null,end: null}; }; //ua utils.env = (function() { var os = {}, ua = navigator.userAgent, android = ua.match(/(Android)[/s//]+([/d/.]+)/), ios = ua.match(/(iPad|iPhone|iPod)/s+OS/s([/d_/.]+)/), wp = ua.match(/(Windows/s+Phone)/s([/d/.]+)/), isWebkit = /WebKit//[/d.]+/i.test(ua), isSafari = ios ? (navigator.standalone ? isWebkit : (/Safari/i.test(ua) && !/CriOS/i.test(ua) && !/MQQBrowser/i.test(ua))) : false; if (android) { os.android = true; os.version = android[2]; } if (ios) { os.ios = true; os.version = ios[2].replace(/_/g, '.'); os.ios7 = /^7/.test(os.version); if (ios[1] === 'iPad') { os.ipad = true; } else if (ios[1] === 'iPhone') { os.iphone = true; os.iphone5 = screen.height == 568; } else if (ios[1] === 'iPod') { os.ipod = true; } } if (isWebkit) { os.webkit = true; } if (isSafari) { os.safari = true; } return os; })(); //已配置 tap hold swipe表示是否开启手势 //tapTime tap事件延迟触发的时间 //holdTime hold事件多少秒后触发 //tapMaxDistance 触发tap的时候 最小的移动范围 //swipeMinDistance 触发swipe的时候 最小的移动范围 //swipeTime touchstart 到touchend之前的时间 如果小于swipeTime 才会触发swipe手势 var config = { tap: true, tapMaxDistance: 10, hold: true, tapTime: 200, holdTime: 650, swipe: true, swipeTime: 300, swipeMinDistance: 18 }; var smrEventList = { TOUCH_START: 'touchstart', TOUCH_MOVE: 'touchmove', TOUCH_END: 'touchend', TOUCH_CANCEL: 'touchcancel', SWIPE_START: 'swipestart', SWIPING: 'swiping', SWIPE_END: 'swipeend', SWIPE_LEFT: 'swipeleft', SWIPE_RIGHT: 'swiperight', SWIPE_UP: 'swipeup', SWIPE_DOWN: 'swipedown', SWIPE: 'swipe', HOLD: 'hold', TAP: 'tap', }; /** 手势识别 */ //记录 开始 移动 结束时候的位置 var pos = { start: null, move: null, end: null }; var __touchStart = true; var __tapped; var __prev_tapped_end_time; var __prev_tapped_pos; var __holdTimer = null; var startTime; var startEvent; var moveEvent; var endEvent; var startSwiping; var gestures = { swipe: function(ev) { var el = ev.target; if (!__touchStart || !pos.move || utils.getFingers(ev) > 1) { return; } //计算 时间 距离 角度 var now = Date.now(); var touchTime = now - startTime; var distance = utils.getDistance(pos.start[0], pos.move[0]); var angle = utils.getAngle(pos.start[0], pos.move[0]); var direction = utils.getDirectionFromAngle(angle); var touchSecond = touchTime / 1000; var eventObj = { type: smrEventList.SWIPE, originEvent: ev, direction: direction, distance: distance, distanceX: pos.move[0].x - pos.start[0].x, distanceY: pos.move[0].y - pos.start[0].y, x: pos.move[0].x - pos.start[0].x, y: pos.move[0].y - pos.start[0].y, angle: angle, duration: touchTime, fingersCount:
新闻热点
疑难解答