移動web端自定義tap與模擬hover效果

在上兩篇文章【10行代碼搞定移動web端自定義tap事件】【移動web端模擬hover效果】中分別對移動web端的自定義tap事件、模擬hover效果的原理進行了簡單的說明。這篇文章主要把二者結合在了一塊兒,解決了一些bug,使得總體效果更佳。web

以前的自定義tap沒有考慮到雙擊、長按等使用場景(感謝 @超級小麪包 的建議!),此次新增了langTap、doubleTap事件。模擬hover效果因爲是獨立於自定義tap的,效果有些小瑕疵,此次結合了tap,效果好了不少segmentfault

效果預覽

移動端預覽 源碼this

核心代碼

//tap定時器
var timer_tap;
//langTap定時器
var timer_langTap;

//自定義tap、doubleTap、langTap
$(document).on("touchstart", function (e) {
    var $target = $(e.target);
    var tapData = $target.data("tapData");
    //不處理含有disable class的對象
    if ($target.hasClass("disable")) return;

    //狀態信息
    tapData = tapData ? tapData : {};
    tapData.state = "start";
    tapData.isMoved = 0;
    tapData.preTouchStartTime = tapData.touchStartTime ? tapData.touchStartTime : null;
    tapData.touchStartTime = new Date().getTime();

    //doubleTap
    if(tapData.preTouchStartTime && tapData.touchStartTime - tapData.preTouchStartTime < 250) {
        //doubleTap
        tapData.doubleTapTime = tapData.touchStartTime;
        //記錄信息
        $target.data("tapData", tapData);
        //清除timer_tap
        clearTimeout(timer_tap);
        return;
    }

    //langTap
    timer_langTap = setTimeout(function() {
        var tapData = $target.data("tapData");
        if(tapData.state != "start") return;
        $target.trigger("langTap");
        if(tapData.$hover) tapData.$hover.removeClass("active");
    }, 700);

    //尋找$hover對象
    var $hover;
    if($target.hasClass("action-btn")) {
        $hover = $target;
    }else {
        $target.parents().each(function() {
            if($(this).hasClass("action-btn")) $hover = $hover ? $hover : $(this);
        });
    }
    tapData.$hover = $hover;
    //記錄信息
    $target.data("tapData", tapData);

    //點擊效果
    if(!$hover) return;
    //延遲78ms
    setTimeout(function() {
        var tapData = $target.data("tapData");
        //移動過
        if(tapData.isMoved != 0) return;
        //添加點擊效果
        tapData.$hover.addClass("active");
    }, 78);
});

$(document).on("touchmove", function (e) {
    var $target = $(e.target);
    var tapData = $target.data("tapData");
    //不處理含有disable class的對象
    if ($target.hasClass("disable")) return;
    //記錄信息
    tapData.state = "move";
    tapData.isMoved = 1;
    tapData.touchStartTime = 0;
    $target.data("tapData", tapData);

    //點擊效果
    if(tapData.$hover) tapData.$hover.removeClass("active");
});

$(document).on("touchend", function (e) {
    var $target = $(e.target);
    var tapData = $target.data("tapData");
    //不處理含有disable class的對象
    if ($target.hasClass("disable")) return;
    //清除長按倒計時
    clearTimeout(timer_langTap);
    //記錄信息
    tapData.state = "end";
    $target.data("tapData", tapData);
    //是否移動過
    if (tapData.isMoved == 1) return;
    //觸摸時間
    var duration = new Date().getTime() - tapData.touchStartTime;

    //doubleTap
    if(tapData.doubleTapTime == tapData.touchStartTime) {

        //觸發doubleTap
        $target.trigger("doubleTap");
        if(tapData.$hover) tapData.$hover.removeClass("active");

        //重置開始點擊事件(防止連續觸發doubleTap)
        tapData.touchStartTime = 0;
        $target.data("tapData", tapData);
        return;
    }

    //tap
    if(duration <= 250) {

        //點擊效果持續250ms
        timer_tap = setTimeout(function() {

            //tap
            $target.trigger("tap");
            if(tapData.$hover) tapData.$hover.removeClass("active");

        }, 250 - duration);
        return;
    }

    //觸摸時間在250ms到700ms之間
    if(tapData.$hover) tapData.$hover.removeClass("active");
});

$(document).on("touchcancel", function (e) {
    var $target = $(e.target);
    var tapData = $target.data("tapData");
    if(tapData.$hover) tapData.$hover.removeClass("active");
});

新增內容

langTap

觸發條件:當用戶觸摸屏幕的時間達到700ms時且未移動過code

//langTap
timer_langTap = setTimeout(function() {
    var tapData = $target.data("tapData");
    if(tapData.state != "start") return;
    $target.trigger("langTap");
    if(tapData.$hover) tapData.$hover.removeClass("active");
}, 700);

doubleTap

觸發條件:用戶在250ms內連續觸摸屏幕兩次對象

//doubleTap
if(tapData.preTouchStartTime && tapData.touchStartTime - tapData.preTouchStartTime < 250) {
    //doubleTap
    tapData.doubleTapTime = tapData.touchStartTime;
    //記錄信息
    $target.data("tapData", tapData);
    //清除timer_tap
    clearTimeout(timer_tap);
    return;
}

其餘

自定義tap和模擬hover效果的原理在上兩篇文章中都有說明,這裏就再也不贅述了(主要是不知道該怎麼描述了(-_-))。事件

文章有什麼不對的地方,望你們指正。歡迎交流!rem

相關文章
相關標籤/搜索