原文地址:https://github.com/AlloyTeam/AlloyTouch/wiki/Pull-to-refreshhtml
在手機QQ內部,其實客戶端提供了下拉刷新的能力,拖動整個webview進行下拉刷新,loading以及loading相關的wording和動畫都是客戶端的。解決了一部分須要下拉場景的問題。可是在某些場景下,仍是須要web擁有自身的下拉刷新的能力。好比:github
而拖動整個webview的下拉刷新沒法知足這些場景。AlloyTouch很明顯很是擅長處理web下拉刷新的需求。web
pullRefresh在AlloyTouch header的下面,其中:
header zIndex > pullRefresh zIndex >wrapper和scroller的 zIndex。app
看以看到,下拉到必定程度,箭頭有個旋轉動畫,以及wording描述也會變化。這裏主要利用js去切換class去實現,動畫使用CSS transition實現。因此要預先定義好兩種class。svg
.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的切換。動畫
<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的效果。ui
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); }
不廢話,都在註釋裏。this
Github:https://github.com/AlloyTeam/AlloyTouchcode
任何意見和建議歡迎new issue,AlloyTouch團隊會第一時間反饋。