標籤:
tap事件tap 事件相當於 pc 瀏覽器中的 click 效果,雖然在觸屏裝置上 click 事件仍然可用,但是在很多裝置上,click 會存在一些延遲,如果想要快速響應的 “click” 事件,需要藉助 touch 事件來實現。
element.addeventlistener( ‘touchstart‘, function( e ){ var touches = e.touches[0]; starttx = touches.clientx; startty = touches.clienty;}, false );element.addeventlistener( ‘touchend‘, function( e ){ var touches = e.changedtouches[0], endtx = touches.clientx, endty = touches.clienty; // 在部分裝置上 touch 事件比較靈敏,導致按下和鬆開手指時地事件座標會出現一點點變化 if( math.abs(starttx - endtx) < 6 && math.abs(startty - endty) < 6 ){ console.log( ‘fire tap event‘ ); }}, false );
對於上面代碼;可以再封裝一下:
<button id="btn">點擊</button><script>var mySky = { tap: function(obj, fun) { var start_x = 0, start_y = 0; obj.addEventListener(‘touchstart‘,function(e){ start_x = e.touches[0].clientX; start_y = e.touches[0].clientY; //IE下此屬性不規範,它們的最小值不是0而是2 document.addEventListener(‘touchend‘, touEnd, false); }); function touEnd(e){ var endX = e.changedTouches[0].clientX, endY = e.changedTouches[0].clientY; if(Math.abs(endX - start_x) < 6 && Math.abs(endY - start_y) < 6) { fun.call(obj,e); } document.removeEventListener(‘touchend‘, touEnd, false); }; }} var btn=document.getElementById("btn"); mySky.tap(btn,function(){ alert(‘我可以點擊‘); });</script>
doubleTap事件doubleTap 事件是當手指在相同位置範圍內和極短的時間內兩次敲擊螢幕時觸發的事件。在部分瀏覽器下,doubleTap 事件會選中文本,如果不希望選中文本,可以給元素添加 user-select:none 的 css 屬性。
var isTouchEnd = false, lastTime = 0, lastTx = null, lastTy = null, firstTouchEnd = true, body = document.body, dTapTimer, startTx, startTy, startTime; element.addEventListener( ‘touchstart‘, function( e ){ if( dTapTimer ){ clearTimeout( dTapTimer ); dTapTimer = null; } var touches = e.touches[0]; startTx = touches.clientX; startTy = touches.clientY; }, false ); element.addEventListener( ‘touchend‘, function( e ){ var touches = e.changedTouches[0], endTx = touches.clientX, endTy = touches.clientY, now = Date.now(), duration = now - lastTime; // 首先要確保能觸發單次的 tap 事件 if( Math.abs(startTx - endTx) < 6 && Math.abs(startTx - endTx) < 6 ){ // 兩次 tap 的間隔確保在 500 毫秒以內 if( duration < 301 ){ // 本次的 tap 位置和上一次的 tap 的位置允許一定範圍內的誤差 if( lastTx !== null && Math.abs(lastTx - endTx) < 45 && Math.abs(lastTy - endTy) < 45 ){ firstTouchEnd = true; lastTx = lastTy = null; console.log( ‘fire double tap event‘ ); } } else{ lastTx = endTx; lastTy = endTy; } } else{ firstTouchEnd = true; lastTx = lastTy = null; } lastTime = now;}, false ); // 在 iOS 的 safari 上手指敲擊螢幕的速度過快,// 有一定的幾率會導致第二次不會響應 touchstart 和 touchend 事件// 同時手指長時間的touch不會觸發click if( ~navigator.userAgent.toLowerCase().indexOf(‘iphone os‘) ){ body.addEventListener( ‘touchstart‘, function( e ){ startTime = Date.now(); }, true ); body.addEventListener( ‘touchend‘, function( e ){ var noLongTap = Date.now() - startTime < 501; if( firstTouchEnd ){ firstTouchEnd = false; if( noLongTap && e.target === element ){ dTapTimer = setTimeout(function(){ firstTouchEnd = true; lastTx = lastTy = null; console.log( ‘fire double tap event‘ ); }, 400 ); } } else{ firstTouchEnd = true; } }, true ); // iOS 上手指多次敲擊螢幕時的速度過快不會觸發 click 事件element.addEventListener( ‘click‘, function( e ){ if( dTapTimer ){ clearTimeout( dTapTimer ); dTapTimer = null; firstTouchEnd = true; }}, false ); }
longTap事件longTap 事件是當手指長時間按住螢幕保持不動時觸發的事件。
var startTx, startTy, lTapTimer; element.addEventListener( ‘touchstart‘, function( e ){ if( lTapTimer ){ clearTimeout( lTapTimer ); lTapTimer = null; } var touches = e.touches[0]; startTx = touches.clientX; startTy = touches.clientY; lTapTimer = setTimeout(function(){ console.log( ‘fire long tap event‘ ); }, 1000 ); e.preventDefault();}, false ); element.addEventListener( ‘touchmove‘, function( e ){ var touches = e.touches[0], endTx = touches.clientX, endTy = touches.clientY; if( lTapTimer && (Math.abs(endTx - startTx) > 5 || Math.abs(endTy - startTy) > 5) ){ clearTimeout( lTapTimer ); lTapTimer = null; }}, false ); element.addEventListener( ‘touchend‘, function( e ){ if( lTapTimer ){ clearTimeout( lTapTimer ); lTapTimer = null; }}, false );
swipe事件swipe 事件是當手指在螢幕上滑動後觸發的事件,根據手指滑動的方向又分為 swipeLeft (向左)、swipeRight (向右)、swipeUp (向上)、swipeDown (向下)。
var isTouchMove, startTx, startTy; element.addEventListener( ‘touchstart‘, function( e ){ var touches = e.touches[0]; startTx = touches.clientX; startTy = touches.clientY; isTouchMove = false;}, false ); element.addEventListener( ‘touchmove‘, function( e ){ isTouchMove = true; e.preventDefault();}, false ); element.addEventListener( ‘touchend‘, function( e ){ if( !isTouchMove ){ return; } var touches = e.changedTouches[0], endTx = touches.clientX, endTy = touches.clientY, distanceX = startTx - endTx distanceY = startTy - endTy, isSwipe = false; if( Math.abs(distanceX) >= Math.abs(distanceY) ){ if( distanceX > 20 ){ console.log( ‘fire swipe left event‘ ); isSwipe = true; } else if( distanceX < -20 ){ console.log( ‘fire swipe right event‘ ); isSwipe = true; } } else{ if( distanceY > 20 ){ console.log( ‘fire swipe up event‘ ); isSwipe = true; } else if( distanceY < -20 ){ console.log( ‘fire swipe down event‘ ); isSwipe = true; } } if( isSwipe ){ console.log( ‘fire swipe event‘ ); }}, false );
完成封裝:
https://github.com/chenmnkken/monoevent/wiki/MonoEvent-%E7%9A%84%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3
http://levi.cg.am/archives/3546
移動端 事件常用函數 整理備份