手势识别与事件库 Touch.js若干问题及解决方法
来源:互联网 发布:js attr style 编辑:程序博客网 时间:2024/06/05 20:42
Touch.js是移动设备上的手势识别与事件库, 由百度云Clouda团队维护,也是在百度内部广泛使用的开发工具.
Touch.js的代码已托管于github并开源,希望能帮助国内更多的开发者学习和开发出优秀的App产品.
Touch.js手势库专为移动设备设计, 请在Webkit内核浏览器中使用.
极速CDN
<script src="http://code.baidu.com/touch-0.2.14.min.js"></script>
Examples
//swipe example touch.on('.target', 'swipeleft swiperight', function(ev){ console.log("you have done", ev.type);});
向左及向右 滑动更灵活的解决方案
参考牛人博客的代码,据说相当好用。
1(function(global,doc,factoryFn){ 2 //初始化toucher主方法 3 var factory = factoryFn(global,doc); 4 5 //提供window.util.toucher()接口 6 global.util = global.util || {}; 7 global.util.toucher = global.util.toucher || factory; 8 9 //提供CommonJS规范的接口 10 global.define && define(function(require,exports,module){ 11 //对外接口 12 return factory; 13 }); 14 })(this,document,function(window,document){ 15 /** 16 * 判断是否拥有某个class 17 */ 18 function hasClass(dom,classSingle){ 19 return dom.className.match(new RegExp('(\\s|^)' + classSingle +'(\\s|$)')); 20 } 21 22 /** 23 * @method 向句柄所在对象增加事件监听 24 * @description 支持链式调用 25 * 26 * @param string 事件名 27 * @param [string] 事件委托至某个class(可选) 28 * @param function 符合条件的事件被触发时需要执行的回调函数 29 * 30 */ 31 function ON(eventStr,a,b){ 32 this._events = this._events || {}; 33 var className,fn; 34 if(typeof(a) == 'string'){ 35 className = a.replace(/^\./,''); 36 fn = b; 37 }else{ 38 className = null; 39 fn = a; 40 } 41 //检测callback是否合法,事件名参数是否存在· 42 if(typeof(fn) == 'function' && eventStr && eventStr.length){ 43 var eventNames = eventStr.split(/\s+/); 44 for(var i=0,total=eventNames.length;i<total;i++){ 45 46 var eventName = eventNames[i]; 47 //事件堆无该事件,创建一个事件堆 48 if(!this._events[eventName]){ 49 this._events[eventName] = []; 50 } 51 this._events[eventName].push({ 52 'className' : className, 53 'fn' : fn 54 }); 55 } 56 } 57 58 //提供链式调用的支持 59 return this; 60 } 61 62 /** 63 * @method 事件触发器 64 * @description 根据事件最原始被触发的target,逐级向上追溯事件绑定 65 * 66 * @param string 事件名 67 * @param object 原生事件对象 68 */ 69 function EMIT(eventName,e){ 70 this._events = this._events || {}; 71 //事件堆无该事件,结束触发 72 if(!this._events[eventName]){ 73 return 74 } 75 //记录尚未被执行掉的事件绑定 76 var rest_events = this._events[eventName]; 77 78 //从事件源:target开始向上冒泡 79 var target = e.target; 80 while (1) { 81 //若没有需要执行的事件,结束冒泡 82 if(rest_events.length ==0){ 83 return; 84 } 85 //若已经冒泡至顶,检测顶级绑定,结束冒泡 86 if(target == this.dom || !target){ 87 //遍历剩余所有事件绑定 88 for(var i=0,total=rest_events.length;i<total;i++){ 89 var classStr = rest_events[i]['className']; 90 var callback = rest_events[i]['fn']; 91 //未指定事件委托,直接执行 92 if(classStr == null){ 93 event_callback(eventName,callback,target,e); 94 } 95 } 96 return; 97 } 98 99 //当前需要校验的事件集100 var eventsList = rest_events;101 //置空尚未执行掉的事件集102 rest_events = [];103 104 //遍历事件所有绑定105 for(var i=0,total=eventsList.length;i<total;i++){106 var classStr = eventsList[i]['className'];107 var callback = eventsList[i]['fn'];108 //符合事件委托,执行109 if(hasClass(target,classStr)){110 //返回false停止事件冒泡及后续事件,其余继续执行111 if(event_callback(eventName,callback,target,e) == false){112 return113 }114 }else{115 //不符合执行条件,压回到尚未执行掉的列表中116 rest_events.push(eventsList[i]);117 }118 }119 //向上冒泡120 target = target.parentNode;121 }122 }123 124 /**125 * 执行绑定的回调函数,并创建一个事件对象126 * @param[string]事件名127 * @param[function]被执行掉的函数128 * @param[object]指向的dom129 * @param[object]原生event对象130 */131 function event_callback(name,fn,dom,e){132 var touch = e.touches.length ? e.touches[0] : {};133 134 var newE = {135 'type' : name,136 'target' : e.target,137 'pageX' : touch.clientX || 0,138 'pageY' : touch.clientY || 0139 };140 //为swipe事件增加交互初始位置及移动距离141 if(name == 'swipe' && e.startPosition){142 newE.startX = e.startPosition['pageX'],143 newE.startY = e.startPosition['pageY'],144 newE.moveX = newE.pageX - newE.startX,145 newE.moveY = newE.pageY - newE.startY146 }147 var call_result = fn.call(dom,newE);148 //若绑定方法返回false,阻止浏览器默认事件149 if(call_result == false){150 e.preventDefault();151 e.stopPropagation();152 }153 154 return call_result;155 }156 /**157 * 判断swipe方向158 */159 function swipeDirection(x1, x2, y1, y2) {160 return Math.abs(x1 - x2) >=161 Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down')162 }163 164 /**165 * 监听原生的事件,主动触发模拟事件166 * 167 */168 function eventListener(DOM){169 var this_touch = this;170 171 //轻击开始时间172 var touchStartTime = 0;173 174 //记录上一次点击时间175 var lastTouchTime = 0;176 177 //记录初始轻击的位置178 var x1,y1,x2,y2;179 180 //轻击事件的延时器181 var touchDelay;182 183 //测试长按事件的延时器184 var longTap;185 186 //记录当前事件是否已为等待结束的状态187 var isActive = false;188 //记录有坐标信息的事件189 var eventMark = null;190 //单次用户操作结束191 function actionOver(e){192 isActive = false;193 clearTimeout(longTap);194 clearTimeout(touchDelay);195 }196 197 //触屏开始198 function touchStart(e){199 //缓存事件200 eventMark = e;201 202 x1 = e.touches[0].pageX;203 y1 = e.touches[0].pageY;204 x2 = 0;205 y2 = 0;206 isActive = true;207 touchStartTime = new Date();208 EMIT.call(this_touch,'swipeStart',e);209 //检测是否为长按210 clearTimeout(longTap);211 longTap = setTimeout(function(){212 actionOver(e);213 //断定此次事件为长按事件214 EMIT.call(this_touch,'longTap',e);215 },500);216 }217 //触屏结束218 function touchend(e){219 //touchend中,拿不到坐标位置信息,故使用全局保存下的事件220 EMIT.call(this_touch,'swipeEnd',eventMark);221 if(!isActive){222 return223 }224 var now = new Date();225 if(now - lastTouchTime > 260){226 touchDelay = setTimeout(function(){227 //断定此次事件为轻击事件228 actionOver();229 EMIT.call(this_touch,'singleTap',eventMark);230 },250);231 }else{232 clearTimeout(touchDelay);233 actionOver(e);234 //断定此次事件为连续两次轻击事件235 EMIT.call(this_touch,'doubleTap',eventMark);236 }237 lastTouchTime = now;238 }239 240 //手指移动241 function touchmove(e){242 //缓存事件243 eventMark = e;244 //在原生事件基础上记录初始位置(为swipe事件增加参数传递)245 e.startPosition = {246 'pageX' : x1,247 'pageY' : y1248 };249 //断定此次事件为移动事件250 EMIT.call(this_touch,'swipe',e);251 252 if(!isActive){253 return254 }255 x2 = e.touches[0].pageX256 y2 = e.touches[0].pageY257 if(Math.abs(x1-x2)>2 || Math.abs(y1-y2)>2){258 //断定此次事件为移动手势259 var direction = swipeDirection(x1, x2, y1, y2);260 EMIT.call(this_touch,'swipe' + direction,e);261 }else{262 //断定此次事件为轻击事件263 actionOver(e);264 EMIT.call(this_touch,'singleTap',e);265 }266 actionOver(e);267 }268 269 /**270 * 对开始手势的监听271 */272 DOM.addEventListener('touchstart',touchStart);273 DOM.addEventListener('MSPointerDown',touchStart);274 DOM.addEventListener('pointerdown',touchStart);275 276 /**277 * 对手势结束的监听(轻击)278 */279 DOM.addEventListener('touchend',touchend);280 DOM.addEventListener('MSPointerUp',touchend);281 DOM.addEventListener('pointerup',touchend);282 283 /**284 * 对移动手势的监听285 */286 DOM.addEventListener('touchmove',touchmove);287 DOM.addEventListener('MSPointerMove',touchmove);288 DOM.addEventListener('pointermove',touchmove);289 290 /**291 * 对移动结束的监听292 */293 DOM.addEventListener('touchcancel',actionOver);294 DOM.addEventListener('MSPointerCancel',actionOver);295 DOM.addEventListener('pointercancel',actionOver);296 }297 298 /**299 * touch类300 * 301 */302 function touch(DOM,param){303 var param = param || {};304 305 this.dom = DOM;306 //监听DOM原生事件307 eventListener.call(this,this.dom);308 }309 //拓展事件绑定方法310 touch.prototype['on'] = ON;311 312 //对外提供接口313 return function (dom){314 return new touch(dom);315 };316 });
解决除谷歌浏览器之外的浏览器兼容性方案
1:jquery mobile里面的touch组件。
1:百度的童鞋们实现的touch.js.网址也贴一下吧: http://touch.code.baidu.com/
3:参考大神的:
(function($) { var options, Events, Touch; options = { x: 20, y: 20 }; Events = ['swipe', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown', 'tap', 'longTap', 'drag']; Events.forEach(function(eventName) { $.fn[eventName] = function() { var touch = new Touch($(this), eventName); touch.start(); if (arguments[1]) { options = arguments[1] } return this.on(eventName, arguments[0]) } }); Touch = function() { var status, ts, tm, te; this.target = arguments[0]; this.e = arguments[1] }; Touch.prototype.framework = function(e) { e.preventDefault(); var events; if (e.changedTouches) events = e.changedTouches[0]; else events = e.originalEvent.touches[0]; return events }; Touch.prototype.start = function() { var self = this; self.target.on("touchstart", function(event) { event.preventDefault(); var temp = self.framework(event); var d = new Date(); self.ts = { x: temp.pageX, y: temp.pageY, d: d.getTime() } }); self.target.on("touchmove", function(event) { event.preventDefault(); var temp = self.framework(event); var d = new Date(); self.tm = { x: temp.pageX, y: temp.pageY }; if (self.e == "drag") { self.target.trigger(self.e, self.tm); return } }); self.target.on("touchend", function(event) { event.preventDefault(); var d = new Date(); if (!self.tm) { self.tm = self.ts } self.te = { x: self.tm.x - self.ts.x, y: self.tm.y - self.ts.y, d: (d - self.ts.d) }; self.tm = undefined; self.factory() }) }; Touch.prototype.factory = function() { var x = Math.abs(this.te.x); var y = Math.abs(this.te.y); var t = this.te.d; var s = this.status; if (x < 5 && y < 5) { if (t < 300) { s = "tap" } else { s = "longTap" } } else if (x < options.x && y > options.y) { if (t < 250) { if (this.te.y > 0) { s = "swipeDown" } else { s = "swipeUp" } } else { s = "swipe" } } else if (y < options.y && x > options.x) { if (t < 250) { if (this.te.x > 0) { s = "swipeLeft" } else { s = "swipeRight" } } else { s = "swipe" } } if (s == this.e) { this.target.trigger(this.e); return } }})(window.jQuery || window.Zepto);
0 0
- 手势识别与事件库 Touch.js若干问题及解决方法
- 移动设备手势事件库Touch.js
- js中的touch事件及gesture(手势)事件
- js touch事件 手势滑动事件总结
- js中的touch事件及gesture(手势)事件详解 — 第13.4.9节
- 第19天 Android Touch事件学习 6 手势识别
- 浅谈移动端之js touch事件 手势滑动事件
- JS 触摸与手势事件
- 读书笔记---触摸事件与手势识别
- 触摸事件与手势识别1
- iOS触摸事件与手势识别详解
- [js点滴]触摸事件与手势事件
- touch手势与触摸
- 手势识别事件详解
- iOS个人整理08-touch触摸事件和手势识别器
- appwidget 窗口小部件onTouch事件及手势识别
- appwidget 窗口小部件onTouch事件及手势识别
- appwidget 窗口小部件onTouch事件及手势识别
- poj滑雪(记忆化搜索)
- C 语言的程序的编辑,编译和运行
- Linux内核---47.关于clk_get与clk_enable
- 降采样和上采样(图像)
- setbuf函数使用注意事项
- 手势识别与事件库 Touch.js若干问题及解决方法
- 【打CF,学算法——三星级】CodeForces 567D One-Dimensional Battle Ships (二分)
- 编译链接中的-可重定位目标文件
- Android JavaPoet 动态生成Java源码(1)
- Linux内核---48.spi驱动修改
- 【钜惠预告】黑马程序员暑期抢座活动即将上线
- 链表划分
- iOS开发出现 CUICatalog: Invalid asset name supplied: (null)
- Linux内核---49.i2s驱动分析1测试