Javascript下拉刷新

Html相关代码

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
    </head>
    <body style="background-color: beige;">
        <div id="container" style="100%;border:solid 1px blue; transform:translate(0px,-61px)">
            <div style="height:50px; line-height:50px; text-align:center; 100%; border:solid 1px red;">
                努力加载中...
            </div> 
            <div style="100%; line-height:30px;background-color:#F2F2F2; font-size:17px; font-family:'Adobe Garamond Pro'">
                下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新
                下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新
                下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉刷新下拉拉刷新下拉刷新
            </div>
        </div>
    </body>
</html>
<!--JQuery是那么的好用,这种情况下怎么能没有它呢!-->
<script type="text/javascript" src="http://libs.baidu.com/jquery/1.11.1/jquery.min.js"></script>

JavaScript该做什么呢?  

1、根据滑动轨迹动态调整滑块位置(transfrom=>translate);

2、根据滑动的距离判断是否执行刷新(或数据加载)。

当然,如果滑动结束后使用ajax重新加载页面数据,还将涉及到一个页面向上滑动并隐藏提示部分的效果。

大致思路:

(前提条件:当前元素已滑动至顶部) 

1、当鼠标左键按下(移动设备上的touchstart事件)的时候记录下当前鼠标位置的 Y轴坐标;

2、当鼠标移动的时候(touchmove事件),记录下鼠标的Y 轴坐标判断滑动轨迹并进行相应的滑块移动;

3、当鼠标左键松开(touchend事件)的时候,通过对比鼠标开始和结束的Y轴坐标的距离判断是否应该刷新页面(或重新加载数据)。

上代码:

//下拉刷新方法
    /*
    *obj--滑动对象
    *offset--滑动距离(当滑动距离大于等于offset时将调用callback)
    *callback--滑动完成后的回调函数
    */
    var slide = function (obj, offset, callback) {
        var start,
            end,
            start_time,
            end_time,
            isLock = false,//是否锁定整个操作
            isCanDo = false,//是否移动滑块
            isTouchPad = (/hp-tablet/gi).test(navigator.appVersion),
            hasTouch = 'ontouchstart' in window && !isTouchPad,
            loading = '<div class="loadEffect">' +
                            '<span></span>' +
                            '<span></span>' +
                            '<span></span>' +
                            '<span></span>' +
                            '<span></span>' +
                            '<span></span>' +
                            '<span></span>' +
                            '<span></span>' +
                        '</div>' +
                        '努力加载中...';
        //将对象转换为jquery的对象
        obj = $(obj);
        var objparent = obj.parent();
        /*操作方法*/
        var fn =
            {
                //移动容器
                translate: function (diff) {
                    obj.css({
                        "-webkit-transform": "translate(0," + diff + "px)",
                        "transform": "translate(0," + diff + "px)"
                    });
                },
                //设置效果时间
                setTranslition: function (time) {
                    obj.css({
                        "-webkit-transition": "all " + time + "s",
                        "transition": "all " + time + "s"
                    });
                },
                //返回到初始位置
                back: function () {
                    fn.translate(0 - offset);
                    //标识操作完成
                    isLock = false;
                }
            };
        //滑动开始
        obj.bind("touchstart", function (e) {
            var time = new Date();
            start_time = time.getSeconds();
//            console.log(start_time);
            if (objparent.scrollTop() <= 0 && !isLock) {
                var even = typeof event == "undefined" ? e : event;
                //标识操作进行中
                isLock = true;
                isCanDo = true;
                //保存当前鼠标Y坐标
                start = hasTouch ? even.touches[0].pageY : even.pageY;
                //消除滑块动画时间
                fn.setTranslition(1);
            }
        });
        //滑动中
        obj.bind("touchmove", function (e) {
            if (objparent.scrollTop() <= 0 && isCanDo) {
                var even = typeof event == "undefined" ? e : event;
                //保存当前鼠标Y坐标
                end = hasTouch ? even.touches[0].pageY : even.pageY;
                if (start < end) {
                    even.preventDefault();
                    //消除滑块动画时间
                    fn.setTranslition(0);
                    //移动滑块
                    fn.translate(end - start - offset);
                }
            }
        });
        //滑动结束
        obj.bind("touchend", function (e) {
            var time = new Date();
            end_time = time.getSeconds();
            if (isCanDo) {
                isCanDo = false;
                //判断滑动距离是否大于等于指定值以及判断滑动时间是否超过预定时间
                if (end - start >= offset && end_time - start_time >= 1 ) {
                    $('.slidetxt').html(loading);
                    //设置滑块回弹时间
                    fn.setTranslition(1);
                    //保留提示部分
                    fn.translate(0);
                    //执行回调函数
                    if (typeof callback == "function") {
                        callback.call(fn, e);
                    }
                } else {
                    //返回初始状态
                    fn.back();
                }
            }
        });
    }

代码分析:

1、参数:obj,要滑动的对象;offset,提示部分的transform的值( 代码中是 transform:translate(0px,-61px) ,那么这里就是61 );callback,回调函数,在下拉完成后调用的函数( 页面刷新或数据加载 )。

2、为什么是transform不是margin?

因为transform不会引起重绘,相比margin更流畅,性能更好。但是transfrom有个比较好玩的地方,如果translateY的值为负数 (当前元素上移xx像素) 下方元素不会跟着上移 (margin会上移) ,在这点上它和margin是有区别的 。 注意,这里的-webkit-transform的存在是有必要的,因为有些浏览器识别不了transform,比如微信内置浏览 (我的手机上是这样的) 。为了兼容性,多扣几个字母是值得的。

3、关于transition设置为0s。

为什么要在touchstart的时候把transition的值设置为0秒呢?transition的作用是为元素属性的变化添加过渡效果,例如一个框变大,我们设置为transition为1s,那么这个框就是在1s内变大到指定大小。第一个参数表示设置过渡效果的 CSS 属性的名称 (如:margin,transform;all表示所有) ,第二个参数表示过渡的时间。 代码中设置transition的目的是在于滑动结束后 (手指离开屏幕) 为滑块回弹添加过渡效果,这样看上去就不会那么突兀。当然,这个过渡效果同样会应用到数据加载完成后提示部分的隐藏上。设置为0是为了取消在滑动过程中的滑块过渡效果,我们手指往下滑动的时候,滑块会跟这向下移动,这样就有了滑动滑块的效果。如果这个时候不取消transition就会出现滑块抖动的效果 (嘿嘿,有兴趣的话可以试试这种感觉。) 。整个过程中transition是相当重要的。

4、关于isLock和isCanDo.

这两个变量的作用在于防止二次滑动,在第一次滑动后数据加载完成之前不允许有第二次的滑动。当滑动开始的时候讲isLock和isCanDo都设置为True,表示允许后面两个事件里的代码可以正常运行,当滑动结束后isCanDo设置为false表示在isLock被设置为True之前 (整个操作完成之前) 所有的事件代码均不可用 (不执行下拉数据加载等相关动作) 。

5、如何使用?

$(function () {
    slide("#container", 61, function (e) {
        var that = this;
        setTimeout(function () {
            that.back.call();
        }, 2000);
    });
});

 代码中的setTimeout是用于模拟ajax加载数据的效果,加载数据这部分就没有再单独写过了。JavaScript的回调函数是用着最顺手的特性之一。这里在数据加载完成后需要调用一个back方法,这个方法目的就是重置slide里的各种状态。

原文地址:https://www.cnblogs.com/moumou0213/p/6396380.html