首页 > 代码库 > hml5 自定义滑动控件

hml5 自定义滑动控件

ys_scroll.css

.ys-scroll-wrapper{
    position:relative;
    overflow: auto;
    -webkit-overflow-scrolling: touch;
}

.ys-scroll-wrapper .ys-scroll-content{
    min-height:100%;
}


/* loading-top */
.ys-scroll-wrapper .loading-top {
    display:block;
    width:100%;
    height:40px;
    line-height: 40px;
    text-align: center;
}
/* loading-bottom */
.ys-scroll-wrapper .loading-bottom {
    display:block;
    width:100%;
    height:40px;
    line-height: 40px;
    text-align: center;
}

/* loading-bottom */
.ys-scroll-wrapper .loading-end {
    display:none;
    width:100%;
    height:40px;
    line-height: 40px;
    text-align: center;
}

ys_scroll.js

(function($){

    var defaultSettings = {
        hasArrivedEnd:false,// 是否已经到底部
        pulldownCallback:function(){ // 下拉回调
            console.log("pull down ... ");

        },
        pullupCallback:function(){ // 上拉回调
            console.log("pull up ... ");
        }
    };


    function render(target,settings){

        var container = target;
        var childrenNode = $(container).children().remove();
        $(container).addClass("ys-scroll-wrapper");

        $(container).append("<div class=‘loading-top‘>加载中...</div>");
        $(container).append("<div class=‘ys-scroll-content‘></div>");
        $(container).append("<div class=‘loading-bottom‘>加载更多...</div>");
        $(container).append("<div class=‘loading-end‘>已经到底了</div>");


        $(container).find(".ys-scroll-content").append(childrenNode);

        $(container).scrollTop(LOADING_BAR_HEIGHT);

        $(container).data("settings",settings);
        return container;
    }

    function bindEventHandlers(target,container,settings){


        var loadingTopRevertTimeout = null;
        var loadingTopEndTimeout = null;

        var loadingBottomRevertTimeout = null;
        var loadingBottomTimeout = null;

        var pulldownCallback = settings.pulldownCallback;
        var pullupCallback = settings.pullupCallback;

        function clearTimeouts(){
            clearTimeout(loadingTopRevertTimeout);
            clearTimeout(loadingTopEndTimeout);
            clearTimeout(loadingBottomRevertTimeout);
            clearTimeout(loadingBottomTimeout);
        }

        function scrollHandler(){
            clearTimeouts();

            var loadingTop = false;

            if(arriveLoadingTopStart(container)){
                loadingTopRevertTimeout = setTimeout(function(){
                    loadingTopRevert(container);
                },RESPONSE_DELAY);
                loadingTop = true;
            }

            if(arriveLoadingTopEnd(container)){
                clearTimeouts();

                loadingTopEndTimeout = setTimeout(function(){
                    resetLoading(container);
                    pulldownCallback();
                },RESPONSE_DELAY);
                loadingTop = true;
            }

            var hasArrivedEnd = $(container).data("settings").hasArrivedEnd;
            if(hasArrivedEnd||loadingTop){ // 如果已经到底了不需要额外操作
                return;
            }


            if(arriveLoadingBottomStart(container)){
                loadingBottomRevertTimeout = setTimeout(function(){
                    loadingBottomRevert(container);
                },RESPONSE_DELAY);
            }

            if(arriveLoadingBottomEnd(container)){
                clearTimeouts();

                loadingBottomTimeout = setTimeout(function(){
                    pullupCallback();
                },RESPONSE_DELAY)
            }
        }


        var hasPressed = false;
        $(container).on("touchstart",function(event){
            hasPressed = true;
            clearTimeouts();
            stopAnimation(container);
        });

        $(container).on("touchmove",function(event){

            hasPressed = true;
            clearTimeouts();
            stopAnimation(container);

            var clientX = event.originalEvent.changedTouches[0].clientX;
            var clientY = event.originalEvent.changedTouches[0].clientY;
            if(clientY<0||clientX<0){
                scrollHandler();
            }
        });

        $(container).on("touchend touchcancel",function(event){
            scrollHandler();
            hasPressed = false;
        });

        $(container).scroll(function(){
            if(hasPressed||reverting){
                return;
            }
            scrollHandler();
        });
    }

    var RESPONSE_DELAY = 800; // 触发延迟
    var ANIMATION_DURATION = 300; // 动画持续时间
    var LOADING_BAR_HEIGHT = 40; // loading bar 高度

    var reverting = false; // 动画正在恢复

    function stopAnimation(container){
        $(container).stop(true);
        reverting = false;
    }

    function loadingTopRevert(container){
        reverting = true;
        $(container).animate({
            "scrollTop":LOADING_BAR_HEIGHT+"px"
        },ANIMATION_DURATION,function(){
            reverting = false;
        });
    }

    /* 判断达到 Loading-top开始处 */
    function arriveLoadingTopStart(container){
        var scrollTop = $(container).scrollTop();
        if(scrollTop<LOADING_BAR_HEIGHT){
            return true;
        }
        return false;
    }

    /* 判断达到 Loading-top结束处 */
    function arriveLoadingTopEnd(container){
        var scrollTop = $(container).scrollTop();

        if (scrollTop<1) {
            return true;
        }
        return false;
    }

    function loadingBottomRevert(container){
        reverting = true;
        var clientHeight = $(container).height();
        var scrollTop = $(container)[0].scrollHeight-LOADING_BAR_HEIGHT-clientHeight;
        $(container).animate({
            "scrollTop":scrollTop+"px"
        },ANIMATION_DURATION,function(){
            reverting = false;
        });

    }

    /* 判断到达 Loading Bottom 开始处 */
    function arriveLoadingBottomStart(container){
        var scrollTop = $(container).scrollTop();
        var scrollHeight = $(container)[0].scrollHeight;
        var clientHeight = $(container).height();


        if (scrollTop + clientHeight+LOADING_BAR_HEIGHT>= scrollHeight) {
            return true;
        }
        return false;
    }

    /* 判断到达 Loading Bottom 结束处 */
    function arriveLoadingBottomEnd(container){
        var scrollTop = $(container).scrollTop();
        var scrollHeight = $(container)[0].scrollHeight;
        var clientHeight = $(container).height();
        if (scrollTop + clientHeight+1> scrollHeight) {
            return true;
        }
        return false;
    }

    /* 重设 loading */
    function resetLoading(container){
        $(container).data("settings").hasArrivedEnd=false;
        $(container).find(".loading-bottom").show();
        $(container).find(".loading-end").hide();
    }

    /* 设置loading end */
    function setLoadingEnd(container){
        $(container).data("settings").hasArrivedEnd=true;
        $(container).find(".loading-bottom").hide();
        $(container).find(".loading-end").show();
    }



    var options = {
        ysScroll:function(settings) {
            var mergedSettings = {};
            $.extend(mergedSettings,defaultSettings,settings);


            $(this).each(function(){
                var container = render(this,settings);
                $(container).data("settings",settings);
                bindEventHandlers(this,container,mergedSettings);
            });
        },
        ysScrollRefresh:function(){
            if(arriveLoadingTopStart(this)){
                loadingTopRevert(this);
            }

            if(arriveLoadingBottomStart(this)){
                loadingBottomRevert(this);
            }
        },

        ysScrollLoadEnd:function(){
            setLoadingEnd(this);
        }
    };
    $.fn.extend(options);
})(jQuery);

测试页面 scroll.html

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title></title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <meta name="format-detection" content="telephone=no">
    <link href="http://www.mamicode.com/css/common/ys_scroll.css" rel="stylesheet">
    <style>
        html,body,.container{
            height:100%;
            margin:0;
            padding:0;
        }
    </style>
</head>
<body>
<div class="container">
    <ul>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
    </ul>
</div>

<script src="http://www.mamicode.com/dist/js/jquery-1.11.3.min.js"></script>
<script src="http://www.mamicode.com/js/common/ys_scroll.js"></script>

<script>
    var dataHtml = $(".container ul").html();

    $(".container ").ysScroll({
        pulldownCallback:function(){ // 下拉回调
            console.log("pull down ... ");

            $(".container ul").html(dataHtml);
            $(".container ").ysScrollRefresh();
        },
        pullupCallback:function(){ // 上拉回调
            console.log("pull up ... ");
            $(".container  ul").append(dataHtml);
            $(".container ").ysScrollRefresh();
        }
    });
</script>
</body>
</html>

注:容器使用前要给其设置一个固定的高度。当触发pulldownCallback,pullupCallback回调后一定要使用$(".container").ysScrollRefresh();重置容器。

hml5 自定义滑动控件