Pull to refresh

dntzhang edited this page Jan 9, 2017 · 1 revision

效果展示

扫码体验

你也可以点击这里访问Demo 可以点击这里查看代码

背景

在手机QQ内部,其实客户端提供了下拉刷新的能力,拖动整个webview进行下拉刷新,loading以及loading相关的wording和动画都是客户端的。解决了一部分需要下拉场景的问题。但是在某些场景下,还是需要web拥有自身的下拉刷新的能力。比如:

  • 需要统一IOS和安卓的体验
  • 需要自定义下拉刷新动画
  • 需要已web内的背景或者其他Dom元素有联动交互反馈

而拖动整个webview的下拉刷新无法满足这些场景。AlloyTouch很明显非常擅长处理web下拉刷新的需求。

页面骨架实现

pullRefresh在AlloyTouch header的下面,其中: header zIndex > pullRefresh zIndex >wrapper和scroller的 zIndex。

下拉动画实现

看以看到,下拉到一定程度,箭头有个旋转动画,以及wording描述也会变化。这里主要利用js去切换class去实现,动画使用CSS transition实现。所以要预先定义好两种class。

.arrow {
    margin-top: 5px;
    margin-bottom: 5px;
}

.arrow:after {
    content: "Pull to refresh";
}
    
.arrow_up.arrow:after {
    content: "Release to refresh";
}

.arrow_up img {
    transform: rotateZ(180deg);
    -webkit-transform: rotateZ(180deg);
}

.pull_refresh img {
    width: 20px;
    transition: transform .4s ease;
}

通过上面定要好的class,在js逻辑里面只需要负责remove和add arrow_up clas便可以实现箭头旋转和wording的切换。

Loading动画实现

<svg width='40px' height='40px' xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" class="uil-default">
    <rect x="0" y="0" width="100" height="100" fill="none" class="bk"></rect><rect x='46.5' y='40' width='7' height='20' rx='5' ry='5' fill='#00a9f2' transform='rotate(0 50 50) translate(0 -30)'>
        <animate attributeName='opacity' from='1' to='0' dur='1s' begin='0s' repeatCount='indefinite' />
    </rect><rect x='46.5' y='40' width='7' height='20' rx='5' ry='5' fill='#00a9f2' transform='rotate(30 50 50) translate(0 -30)'>
        <animate attributeName='opacity' from='1' to='0' dur='1s' begin='0.08333333333333333s' repeatCount='indefinite' />
       ...
       ...
</svg>

loading效果使用SVG去实现,利用12个rect的 indefinite animate去实现。begin代表开始时间有个递增达到loading的效果。

核心实现

var scroller = document.querySelector("#scroller"),
    arrow = document.querySelector("#arrow"),
    pull_refresh = document.querySelector("#pull_refresh"),
    list = document.querySelector("#list"),
    index = 0;

//给pull_refresh注入transform属性并且关闭透视投影
Transform(pull_refresh, true);
//给scroller注入transform属性并且关闭透视投影
Transform(scroller, true);

new AlloyTouch({
    touch: "#wrapper",
    target: scroller, 
    property: "translateY",  
    initialVaule: 0,
    min: window.innerHeight - 45 - 48 - 2000, 
    max: 0,
    change: function (value) {
    	//pull_refresh的translateY由scroller的value决定,所以向下拉scroller的时候,可以拉动pull_refresh
        pull_refresh.translateY = value;
    },
    touchMove: function (evt, value) {
        if (value > 70) { //当下拉到达70px的时候下箭头变成上箭头并且修改wording
        	//为了代码简洁,直接使用classList
            //http://caniuse.com/#search=classList
            //下箭头变成上箭头并且修改wording
            arrow.classList.add("arrow_up");
        } else {  //当下拉未到达70px上箭头变成下箭头并且修改wording
            arrow.classList.remove("arrow_up");
        }
    },
    touchEnd: function (evt, value) {
        if (value > 70) {
        	//运动到60px的地方,用来显示loading
            this.to(60);
            //模拟请求~~~
            mockRequest(this);
            //return false很重要,用来防止执行alloytouch内部超出边界的回弹和惯性运动
            return false;
        }
    }
});

//模拟请求~~~
function mockRequest(at) {
	//显示loading~~
    pull_refresh.classList.add("refreshing");
    //模拟cgi请求
    setTimeout(function () {
        var i = 0,
            len = 3;
        for (; i < len; i++) {
            var li = document.createElement("li");
            li.innerHTML = "new row " + index++;
            list.insertBefore(li, list.firstChild);
        }
        //重置下拉箭头和wording
        arrow.classList.remove("arrow_up");
        //移除loading
        pull_refresh.classList.remove("refreshing");
        //回到初始值
        at.to(at.initialVaule);
        //由于加了三个li,每个li高度为40,所以min要变得更小
        at.min -= 40 * 3;
    }, 500);
}

不废话,都在注释里。

开始AlloyTouch

Github:https://github.com/AlloyTeam/AlloyTouch

任何意见和建议欢迎new issue,AlloyTouch团队会第一时间反馈。

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.