先驗貨
如你體驗所見,流程的滾動的同時還能支援頭部的動畫?不斷地載入新資料還能做到流暢的滑動!怎麼做得的?使用AlloyTouch CSS 0.2.0及以上版本便可!
頭部動畫
載入更多
實現程式碼
var infoList = document.getElementById("infoList"),
mockHTML = infoList.innerHTML,
scroller = document.getElementById("scroller"),
header = document.getElementById("header"),
userLogo = document.getElementById("user-logo-wrapper"),
loading = false,
alloyTouch = null;
Transform(scroller, true);
Transform(header);
header.originY = -70;
header.translateY = -70;
Transform(userLogo);
alloyTouch = new AlloyTouch({
touch: "#wrapper",
vertical: true,
target: scroller,
property: "translateY",
maxSpeed: 2,
outFactor: 0.1,
min: 160 * -20 + window.innerHeight - 202 - 50,
max: 0,
lockDirection: false,
touchStart: function () {
reastMin();
},
lockDirection: false,
change: function (v) {
if (v <= this.min + 5 && !loading) {
loading = true;
loadMore();
}
if (v < 0) {
if (v < -140) v = -140;
var scaleY = (240 + v) / 240;
header.scaleY = scaleY;
userLogo.scaleX = userLogo.scaleY = scaleY;
userLogo.translateY = v / 1.7;
} else {
var scaleY = 1 + v / 240;
header.scaleY = scaleY;
userLogo.scaleX = userLogo.scaleY = scaleY;
userLogo.translateY = v / 1.7;
}
}
})
function loadMore() {
setTimeout(function () {
infoList.innerHTML += mockHTML;
loading = false;
reastMin();
}, 500)
}
function reastMin() {
alloyTouch.min = -1 * parseInt(getComputedStyle(scroller).height) + window.innerHeight - 202;
}
document.addEventListener("touchmove", function (evt) {
evt.preventDefault();
}, false);複製程式碼
就這麼多程式碼。當然你要引用一個transformjs和alloy_touch.css.js。先看這一堆:
Transform(scroller, true);
Transform(header);
header.originY = -70;
header.translateY = -70;
Transform(userLogo);複製程式碼
- Transform(xxx)是什麼意思?
賦予xxx transformation能力
- 第一個scroller加上true代表關閉透視投影,為什麼要關閉透視投影?
因為scroller裡面是有文字,防止文字在IOS中模糊的情況。
- header是頂部的那個藍色的區域。為什麼要設定originY和translateY?為什麼要設定為-70?
因為header的高度為140px,使用者向上滾動的過程中,需要對其進行scaleY變換。通常我們的做法是設定CSS3 transform-origin為 center top。而使用transformjs之後,可以拋棄transform-origin,使用originY或者originX屬性便可。originY 設定為 -70,相對於高度為140的header來說就是center top。
再看這一堆:
alloyTouch = new AlloyTouch({
touch: "#wrapper",
vertical: true,
target: scroller,
property: "translateY",
maxSpeed: 2,
outFactor: 0.1,
lockDirection: false,
min: 160 * -20 + window.innerHeight - 202 - 50,
max: 0,
touchStart: function () {
resetMin();
},
lockDirection: false,
...
...
...
})
...
...
function resetMin() {
alloyTouch.min = -1 * parseInt(getComputedStyle(scroller).height) + window.innerHeight - 202;
}複製程式碼
使用AlloyTouch最關鍵的一點就是計算min和max的值。min和max決定了可以滾到哪裡,到了哪裡會進行回彈等等。這裡max是0毫無疑問。
- 但是min那一堆加減乘除是什麼東西?
這裡首次載入是20行資料,每一行高度大概160,主意是大概, window.innerHeight是視窗的高度,202px是滾動的容器的padding top的值,50px是用來留給顯示載入更多的...
如上圖所示,主要是需要求???的高度。
- 那麼怎麼解決大概160*20的問題?
touchStart的時候reastMin。resetMin會去通過getComputedStyle計算整個scroller的高度。
- maxSpeed是幹什麼用的?
用來限制滾動的最大速度,個人感覺調整到2挺舒適,這個可以根據場景和被運動的屬性靈活配置。
- outFactor是幹什麼用的?
用來設定超出min或者max進行拖拽的運動比例係數,係數越小,超出min和max越難拖動,也就是受到的阻力越大。
- lockDirection是幹什麼用的?
lockDirection預設值是true。代表使用者起手時候是橫向的,而你監聽的是豎直方向的touch,這樣的話是不會觸發運動。只有起手和監聽對應上才會有觸控運動。這裡把lockDirection設定成false就沒有這個限制,不管使用者起手的direction,都會有觸控運動。
再看AlloyTouch注入的change事件!頭部動效核心的一個配置函式:
change: function (v) {
if (v <= this.min + 5 && !loading) {
loading = true;
loadMore();
}
if (v < 0) {
if (v < -140) v = -140;
var scaleY = (240 + v) / 240;
header.scaleY = scaleY;
userLogo.scaleX = userLogo.scaleY = scaleY;
userLogo.translateY = v / 1.7;
} else {
var scaleY = 1 + v / 240;
header.scaleY = scaleY;
userLogo.scaleX = userLogo.scaleY = scaleY;
userLogo.translateY = v / 1.7;
}
}複製程式碼
v代表當前被運動物件的被運動屬性的當前的值,根據這個v去做一些效果和載入更多。
- 什麼時候載入更多?
當滾動你能看到載入更多的時候去載入更多
- 什麼時候能看到載入更多?
v <= this.min + 5。 可以看到change回撥裡可以拿到this,也就是AlloyTouch物件的例項,當v等於this.min代表滾到了底部,所以這裡加上5代表快要滾動底部已經看到了載入更多。就去執行loadMore函式。
- loading是幹什麼用的?
防止重複loadMore用得,因為change執行得很頻繁,所以這裡會通過loading的狀態去鎖上。
- 下面一堆設定scaleX、scaleY、translateY以及一堆數字是怎麼來的?
慢慢除錯得出的最佳效果~~反正就是根據v的數值對映到 header和使用者頭像的transform屬性上,這裡就不一一講了。
再看loadMore:
function loadMore() {
setTimeout(function () {
infoList.innerHTML += mockHTML;
loading = false;
reastMin();
}, 500)
}複製程式碼
這裡使用了一段假的HTML去模擬AJAX非同步請求以及資料轉HTML的過程,整個耗時500ms,500ms後會去:
- 插入HTML
- 重置loading狀態
- 重置AlloyTouch的min
最後:
document.addEventListener("touchmove", function (evt) {
evt.preventDefault();
}, false);複製程式碼
阻止掉整個document的預設事件,不會把整個頁面拖下來,在手Q裡的話,你就看不到網址和X5核心提供技術支援了。
開始AlloyTouch
Github:github.com/AlloyTeam/A…
任何意見和建議歡迎new issue,AlloyTouch團隊會第一時間反饋。