javascript移動(dòng)設(shè)備Web開發(fā)中對(duì)touch事件的封裝實(shí)例
在觸屏設(shè)備上,一些比較基礎(chǔ)的手勢(shì)都需要通過對(duì) touch 事件進(jìn)行二次封裝才能實(shí)現(xiàn)。
zepto 是移動(dòng)端上使用率比較高的一個(gè)類庫(kù),但是其 touch 模塊模擬出來的一些事件存在一些兼容性問題,如 tap 事件在某些安卓設(shè)備上存在事件穿透的 bug,其他類型的事件也或多或少的存在一些兼容性問題。
于是乎,干脆自己動(dòng)手對(duì)這些常用的手勢(shì)事件進(jìn)行了封裝,由于沒有太多真實(shí)的設(shè)備來進(jìn)行測(cè)試,可能存在一些兼容性問題,下面的代碼也只是在 iOS 7、Andorid 4 上的一些比較常見的瀏覽器中測(cè)試通過。
tap事件
tap 事件相當(dāng)于 pc 瀏覽器中的 click 效果,雖然在觸屏設(shè)備上 click 事件仍然可用,但是在很多設(shè)備上,click 會(huì)存在一些延遲,如果想要快速響應(yīng)的 “click” 事件,需要借助 touch 事件來實(shí)現(xiàn)。
var startTx, startTy;
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;
// 在部分設(shè)備上 touch 事件比較靈敏,導(dǎo)致按下和松開手指時(shí)的事件坐標(biāo)會(huì)出現(xiàn)一點(diǎn)點(diǎn)變化
if( Math.abs(startTx - endTx) < 6 && Math.abs(startTy - endTy) < 6 ){
console.log( 'fire tap event' );
}
}, false );
doubleTap事件
doubleTap 事件是當(dāng)手指在相同位置范圍內(nèi)和極短的時(shí)間內(nèi)兩次敲擊屏幕時(shí)觸發(fā)的事件。在部分瀏覽器下,doubleTap 事件會(huì)選中文本,如果不希望選中文本,可以給元素添加 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;
// 首先要確保能觸發(fā)單次的 tap 事件
if( Math.abs(startTx - endTx) < 6 && Math.abs(startTx - endTx) < 6 ){
// 兩次 tap 的間隔確保在 500 毫秒以內(nèi)
if( duration < 301 ){
// 本次的 tap 位置和上一次的 tap 的位置允許一定范圍內(nèi)的誤差
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 上手指敲擊屏幕的速度過快,
// 有一定的幾率會(huì)導(dǎo)致第二次不會(huì)響應(yīng) touchstart 和 touchend 事件
// 同時(shí)手指長(zhǎng)時(shí)間的touch不會(huì)觸發(fā)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 上手指多次敲擊屏幕時(shí)的速度過快不會(huì)觸發(fā) click 事件
element.addEventListener( 'click', function( e ){
if( dTapTimer ){
clearTimeout( dTapTimer );
dTapTimer = null;
firstTouchEnd = true;
}
}, false );
}
longTap事件
longTap 事件是當(dāng)手指長(zhǎng)時(shí)間按住屏幕保持不動(dòng)時(shí)觸發(fā)的事件。
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 事件是當(dāng)手指在屏幕上滑動(dòng)后觸發(fā)的事件,根據(jù)手指滑動(dòng)的方向又分為 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 );
上面模擬的事件都封裝在 MonoEvent 中了。完整代碼地址:https://github.com/chenmnkken/monoevent,需要的朋友看看吧~
PS:這里再為大家推薦一款關(guān)于JS事件的在線查詢工具,歸納總結(jié)了JS常用的事件類型與函數(shù)功能:
javascript事件與功能說明大全:
相關(guān)文章
三種在ES6中將非數(shù)組轉(zhuǎn)換為數(shù)組的方法詳情
這篇文章主要介紹了三種在ES6中將非數(shù)組轉(zhuǎn)換為數(shù)組的方法詳情,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下2022-08-08JavaScript的內(nèi)置對(duì)象Date詳解
這篇文章主要為大家介紹了vue組件通信的幾種方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2021-11-11JS中字符問題(二進(jìn)制/十進(jìn)制/十六進(jìn)制及ASCII碼之間的轉(zhuǎn)換)
對(duì)于js的進(jìn)制轉(zhuǎn)換的一些方法分析2008-11-11JS日期格式化之javascript Date format
這篇文章主要介紹了JS日期格式化之javascript Date format的相關(guān)資料,需要的朋友可以參考下2015-10-10JS動(dòng)態(tài)添加與刪除select中的Option對(duì)象(示例代碼)
本篇文章主要介紹了JS動(dòng)態(tài)添加與刪除select中的Option對(duì)象示例代碼。需要的朋友可以過來參考下,希望對(duì)大家有所幫助2013-12-12Javascript實(shí)現(xiàn)真實(shí)字符串剩余字?jǐn)?shù)提示的實(shí)例代碼
這篇文章介紹了Javascript實(shí)現(xiàn)真實(shí)字符串剩余字?jǐn)?shù)提示的實(shí)例代碼,有需要的朋友可以參考一下2013-10-10js購(gòu)物車實(shí)現(xiàn)思路及代碼(個(gè)人感覺不錯(cuò))
提起購(gòu)物車想必只有在一些購(gòu)物網(wǎng)站上才可以看得到,下面為大家介紹下使用js實(shí)現(xiàn)的購(gòu)物車,感興趣的朋友可以參考下2013-12-12