移動項目開發過程中,經常需要用到滑動的事件來處理一些效果。通常情況下,我們會通過 touchstart->touchmove->touchend 的過程來定義這個事件。這些事件的觸發順序是 touchstart, touchmove, touchmove ….. touchend 。絕大部分平板或手機也正如我們想象的那樣有序執行着。但是以Android 4.0.4為首的一些可惡分子卻有些不聽話:他們的touchend事件沒有如預期的那樣觸發。
監聽這些事件我們會發現,當只是輕點一下屏幕時,touchend可以正常觸發。但是只要當 touchmove 被觸發之后,touchend 就不會再被觸發了,而且 touchmove 也沒有持續觸發。
在網上搜集了一些資料顯示,這是 Android 上瀏覽器的bug
> On Android ICS if no preventDefault is called on touchstart or the firsttouchmove,
> further touchmove events and the touchend will not be fired.
正如提到的我們只需要在 touchstart 或者 touchmove 里執行一下 e.preventDefault(); 就可以避免這個bug。但是,問題來了:添加了 preventDefault 之后,正常的scroll事件也被屏蔽了!我們意外的發現滾動條也不能用了!
於是,我們開始嘗試各種添加preventDefault事件的時機:閉包,延遲,判斷等一一用上。最終焦點落在了firsttouchmove上,於是有了以下代碼。
var touchY = 0; $(this).on('touchstart', function(e){ var touch = e.touches[0]; touchY = touch.clientY; }).on('touchmove', function(e){ var touch = e.touches[0] if(Math.abs(touch.clientY - touchY) < 10){ e.preventDefault(); } }).on('touchend', function(){ // 你的滑動事件 });
基本上主要的思想就是在 touchmove 的時候判斷出縱軸的位移量,當小於某個值的時候就認為是在執行左右滑動,且需要執行 preventDefault 來確保 touchend 可以正常觸發。當然,如果你有橫向滾動條且想綁定上下滑動事件的話就需要自己修改一下代碼。
參考:
http://blog.mobiscroll.com/working-with-touch-events/.