zoukankan      html  css  js  c++  java
  • AlloyTouch实现下拉刷新

    原文地址:https://github.com/AlloyTeam/AlloyTouch/wiki/Pull-to-refresh

    效果展示

    扫码体验

    你也可以点击这里访问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 {
         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团队会第一时间反馈。

  • 相关阅读:
    pycharm下同存Python2和Python3的运行方式问题
    Python3安装requests库
    jmeter实现接口传参为一个文件的测试场景
    解决jmeter添加HTTP Cookie Manager后,还是cookie错误的问题
    jmeter添加webSocket请求
    sublime集成Python环境
    jmeter实现排除登录对单个事务的压测
    JavaScript语法
    JavaScript数据
    javaScript基础
  • 原文地址:https://www.cnblogs.com/iamzhanglei/p/6264692.html
Copyright © 2011-2022 走看看