AlloyTouch實(shí)現(xiàn)下拉刷新
2017-01-09 11:46 【當(dāng)耐特】 閱讀(1819) 評論(0) 收藏 舉報(bào)原文地址:https://github.com/AlloyTeam/AlloyTouch/wiki/Pull-to-refresh
效果展示

掃碼體驗(yàn)

你也可以點(diǎn)擊這里訪問Demo
可以點(diǎn)擊這里查看代碼
背景
在手機(jī)QQ內(nèi)部,其實(shí)客戶端提供了下拉刷新的能力,拖動整個(gè)webview進(jìn)行下拉刷新,loading以及l(fā)oading相關(guān)的wording和動畫都是客戶端的。解決了一部分需要下拉場景的問題。但是在某些場景下,還是需要web擁有自身的下拉刷新的能力。比如:
- 需要統(tǒng)一IOS和安卓的體驗(yàn)
- 需要自定義下拉刷新動畫
- 需要已web內(nèi)的背景或者其他Dom元素有聯(lián)動交互反饋
而拖動整個(gè)webview的下拉刷新無法滿足這些場景。AlloyTouch很明顯非常擅長處理web下拉刷新的需求。
頁面骨架實(shí)現(xiàn)

pullRefresh在AlloyTouch header的下面,其中:
header zIndex > pullRefresh zIndex >wrapper和scroller的 zIndex。
下拉動畫實(shí)現(xiàn)
看以看到,下拉到一定程度,箭頭有個(gè)旋轉(zhuǎn)動畫,以及wording描述也會變化。這里主要利用js去切換class去實(shí)現(xiàn),動畫使用CSS transition實(shí)現(xiàn)。所以要預(yù)先定義好兩種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邏輯里面只需要負(fù)責(zé)remove和add arrow_up clas便可以實(shí)現(xiàn)箭頭旋轉(zhuǎn)和wording的切換。
Loading動畫實(shí)現(xiàn)
<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去實(shí)現(xiàn),利用12個(gè)rect的 indefinite animate去實(shí)現(xiàn)。begin代表開始時(shí)間有個(gè)遞增達(dá)到loading的效果。
核心實(shí)現(xiàn)
var scroller = document.querySelector("#scroller"),
arrow = document.querySelector("#arrow"),
pull_refresh = document.querySelector("#pull_refresh"),
list = document.querySelector("#list"),
index = 0;
//給pull_refresh注入transform屬性并且關(guān)閉透視投影
Transform(pull_refresh, true);
//給scroller注入transform屬性并且關(guān)閉透視投影
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的時(shí)候,可以拉動pull_refresh
pull_refresh.translateY = value;
},
touchMove: function (evt, value) {
if (value > 70) { //當(dāng)下拉到達(dá)70px的時(shí)候下箭頭變成上箭頭并且修改wording
//為了代碼簡潔,直接使用classList
//http://caniuse.com/#search=classList
//下箭頭變成上箭頭并且修改wording
arrow.classList.add("arrow_up");
} else { //當(dāng)下拉未到達(dá)70px上箭頭變成下箭頭并且修改wording
arrow.classList.remove("arrow_up");
}
},
touchEnd: function (evt, value) {
if (value > 70) {
//運(yùn)動到60px的地方,用來顯示loading
this.to(60);
//模擬請求~~~
mockRequest(this);
//return false很重要,用來防止執(zhí)行alloytouch內(nèi)部超出邊界的回彈和慣性運(yùn)動
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);
//由于加了三個(gè)li,每個(gè)li高度為40,所以min要變得更小
at.min -= 40 * 3;
}, 500);
}
不廢話,都在注釋里。
開始AlloyTouch
Github:https://github.com/AlloyTeam/AlloyTouch
任何意見和建議歡迎new issue,AlloyTouch團(tuán)隊(duì)會第一時(shí)間反饋。
浙公網(wǎng)安備 33010602011771號