HTML5滑動(swipe)事件

移動H5開發中經常用到滑動效果(頁面上移、下移、向左滑動、向右滑動等),瀏覽器並沒有內置swipe事件,可以通過touch事件(touchstart、touchmove和touchend)模擬swipe效果。jquery mobile和zeptojs提供了swipe事件。jquery mobile只有swipeLeft和swipeRight,zeptojs提供了完整的tap和swipe事件。

/**
* @author [email protected]
* http://git.oschina.net/accountwcx/rhui
* 
* swipe事件,包括swipeLeft、swipeRight、swipeUp、swipeDown。
* 調用方法
* Rhui.mobile.swipeLeft(el, callback, options)
* Rhui.mobile.swipeRight(el, callback, options)
* Rhui.mobile.swipeUp(el, callback, options)
* Rhui.mobile.swipeDown(el, callback, options)
* 如果使用jQuery,調用方法
* $(el).rhuiSwipe('swipeLeft', callback, options);
* $(el).rhuiSwipe('swipeRight', callback, options);
* $(el).rhuiSwipe('swipeUp', callback, options);
* $(el).rhuiSwipe('swipeDown', callback, options);
*/
(function(window, $){
    var Rhui = window.Rhui || {};
    window.Rhui = Rhui;
    Rhui.mobile = (function(){
        var touch = {
            distance: 30,  //滑動距離,超過該距離觸發swipe事件,單位像素。
            duration: 1000 //滑動時長,超過該時間不觸發swipe,單位毫秒。
        };

        /**
        * 綁定事件
        * @param  el        觸發事件的元素
        * @param  swipe     事件名稱,可選值爲swipeLeft,swipeRight,swipeUp,swipeDown
        * @param  callback  事件回調函數
        * @param  isStopPropagation   是否停止冒泡,true爲停止冒泡
        * @param  isPreventDefault    是否阻止默認事件,true爲阻止默認事件
        * @param  triggerOnMove       swipe事件有兩種觸發方式,一種是在touchmove過程中,只要滿足滑動距離條件即觸發。
        *                             一種是在touchend中,進入滑動距離判斷,如果滿足滑動距離觸發。
        *                             默認是在touchend中觸發。
        */
        function bindSwipe(el, swipe, callback, triggerOnMove, isStopPropagation, isPreventDefault){
            var startPoint, endPoint, timer;

            /**
            * 計算滑動方向
            * 首先根據x方向和y方向滑動的長度決定觸發x方向還是y方向的事件。
            * 然後再判斷具體的滑動方向。
            * 如果滑動距離不夠長,不判斷方向。
            */
            function swipeDirection(x1, y1, x2, y2){
                var diffX = x1 - x2,
                    diffY = y1 - y2,
                    absX = Math.abs(diffX),
                    absY = Math.abs(diffY),
                    swipe;

                if(absX >= absY){
                    if(absX >= touch.distance){
                        swipe = diffX > 0 ? 'swipeLeft' : 'swipeRight';
                    }
                }else{
                    if(absY >= touch.distance){
                        swipe = diffY > 0 ? 'swipeUp' : 'swipeDown';
                    }
                }

                return swipe;
            }

            // 清除本次滑動數據
            function clearSwipe(){
                startPoint = undefined;
                endPoint = undefined;

                if(timer !== undefined){
                    clearTimeout(timer);
                    timer = undefined;
                }
            }

            /**
            * 判斷是否符合條件,如果符合條件就執行swipe事件
            * @param  el     {HTMLElement}  元素
            * @param  event  {Event}        Touch原始事件
            * @param  return 如果執行了事件,就返回true。
            */
            function execSwipe(el, event){
                if(startPoint && endPoint && swipeDirection(startPoint.x, startPoint.y, endPoint.x, endPoint.y) === swipe){
                    callback.call(el, event);
                    return true;
                }
            }

            el.addEventListener('touchstart', function(event){
                var self = this, touchPoint = event.touches[0];

                if(isStopPropagation){
                    event.stopPropagation();
                }

                if(isPreventDefault){
                    event.preventDefault();
                }

                startPoint = {
                    x: Math.floor(touchPoint.clientX),
                    y: Math.floor(touchPoint.clientY)
                };

                timer = setTimeout(function(){
                    //如果超時,清空本次touch數據
                    clearSwipe();
                }, touch.duration);
            });

            el.addEventListener('touchmove', function(event){
                var self = this, touchPoint = event.touches[0];

                if(isStopPropagation){
                    event.stopPropagation();
                }

                if(isPreventDefault){
                    event.preventDefault();
                }

                if(startPoint){
                    endPoint = {
                        x: Math.floor(touchPoint.clientX),
                        y: Math.floor(touchPoint.clientY)
                    };

                    //執行swipe事件判斷,是否符合觸發事件
                    if(triggerOnMove){
                        if(execSwipe(self, event)){
                            clearSwipe();
                        }
                    }
                }
            });

            el.addEventListener('touchend', function(event){
                if(isStopPropagation){
                    event.stopPropagation();
                }

                if(isPreventDefault){
                    event.preventDefault();
                }

                execSwipe(self, event);
                //清除本次touch數據
                clearSwipe();
            });
        }

        /**
        * @param  el        {HTMLElement}  HTML元素
        * @param  callback  {Function}     事件回調函數
        * @param  options   {Object}       可選參數
        *                   isStopPropagation  {Boolean}  是否停止冒泡,true爲停止冒泡
        *                   isPreventDefault   {Boolean}  是否阻止默認事件,true爲阻止默認事件
        *                   triggerOnMove      {Boolean}
        *                                       swipe事件有兩種觸發方式,一種是在touchmove過程中,只要滿足滑動距離條件即觸發。
        *                                       一種是在touchend中,進入滑動距離判斷,如果滿足滑動距離觸發。
        *                                       默認值爲false,在touchend中觸發。
        */
        touch.swipeLeft = function(el, callback, options){
            if(options){
                bindSwipe(el, 'swipeLeft', callback, options.triggerOnMove, options.isStopPropagation, options.isPreventDefault);
            }else{
                bindSwipe(el, 'swipeLeft', callback);
            }

        };

        touch.swipeRight = function(el, callback, options){
            if(options){
                bindSwipe(el, 'swipeRight', callback, options.triggerOnMove, options.isStopPropagation, options.isPreventDefault);
            }else{
                bindSwipe(el, 'swipeRight', callback);
            }
        };

        touch.swipeUp = function(el, callback, options){
            if(options){
                bindSwipe(el, 'swipeUp', callback, options.triggerOnMove, options.isStopPropagation, options.isPreventDefault);
            }else{
                bindSwipe(el, 'swipeUp', callback);
            }
        };

        touch.swipeDown = function(el, callback, options){
            if(options){
                bindSwipe(el, 'swipeDown', callback, options.triggerOnMove, options.isStopPropagation, options.isPreventDefault);
            }else{
                bindSwipe(el, 'swipeDown', callback);
            }
        };

        return touch;
    })();

    // 註冊jquery方法
    if($ && $.fn){
        $.fn.extend({
            /**
            * 模擬touch swipe事件,支持鏈式調用。
            * @param   name      {String}    swipe事件名稱,值有swipLeft、swipeRight、swipeUp、swipeDown。
            * @param   callback  {Function}  swipe事件回調函數
            * @param   opts      {Object}    可選參數
            *                                isStopPropagation  {Boolean}  是否停止冒泡,true爲停止冒泡
            *                                isPreventDefault   {Boolean}  是否阻止默認事件,true爲阻止默認事件
            *                                triggerOnMove      {Boolean}  swipe事件有兩種觸發方式,一種是在touchmove過程中,只要滿足滑動距離條件即觸發。
            *                                                              一種是在touchend中,進入滑動距離判斷,如果滿足滑動距離觸發。
            *                                                              默認值爲false,在touchend中觸發。
            */
            rhuiSwipe: function(name, callback, opts){
                var fnSwipe = Rhui.mobile[name];

                if(this.length > 0 && fnSwipe){
                    this.each(function(){
                        fnSwipe(this, callback, opts);
                    });
                }

                return this;
            }
        });
    }   
})(window, $);


使用實例

<style type="text/css">
    .test{
        width: 400px;
        height: 400px;
    }
</style>
<div id="div1" class="test"></div>
<div class="test"></div>

<script type="text/javascript">
    Rhui.mobile.swipeUp(document.getElementById('div1'), function(event){
        console.log(event);
    }, {
        // 可選參數
        isStopPropagation: true,
        isPreventDefault: true,
        triggerOnMove: true
    });

    $('.test').rhuiSwipe('swipeLeft', function(event){
        console.log(event);
    }, {
        // 可選參數
        isStopPropagation: true,
        isPreventDefault: true,
        triggerOnMove: true
    });
</script>


zeptojs touch事件

zeptojs也提供了滑動事件,該滑動事件需要引用額外的touch.js。

事件 描述
tap 類似PC端瀏覽器的鼠標點擊事件,由於移動瀏覽器點擊事件有延遲,tap提供了無延遲的點擊效果。
singleTap 效果和tap一樣
doubleTap 類似PC端瀏覽器的鼠標雙擊事件
longTap 長按事件,在元素上長按超過0.75秒觸發。有些瀏覽器有默認的長按事件,可能會被覆蓋。
swipe 滑動事件,該事件不考慮滑動方向。
swipeLeft 向左滑動
swipeRight 向右滑動
swipeUp 向上滑動
swipeDown 向下滑動


<style>.delete { display: none; }</style>

<ul id=items>
  <li>List item 1 <span class=delete>DELETE</span></li>
  <li>List item 2 <span class=delete>DELETE</span></li>
</ul>

<script>
// show delete buttons on swipe
$('#items li').swipe(function(){
  $('.delete').hide()
  $('.delete', this).show()
})

// delete row on tapping delete button
$('.delete').tap(function(){
  $(this).parent('li').remove()
})
</script>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章