原文鏈接:https://github.com/AlloyTeam/AlloyTouch/wiki/AlloyTouch-FullPage-Plugin
先驗貨
插件代碼可以在這里找到。
注意,雖然是掃碼體驗,但是AlloyTouch.FullPage特意對鼠標滾輪事件進行了兼容,所以PC上的全屏滾動頁面也可以使用它來快速制作。
使用姿勢
在設計全屏滾動插件的時候,希望開發者幾乎:
- 不用寫任何腳本快速生成精致H5
- 支持PC滾輪和移動觸摸
- 酷炫的轉場動效
- 靈活的時間軸管理
- 一切皆可配置
但是不寫腳本肯定沒有靈活性咯?!不是的。這里不僅僅可以通過在HTML配置一些參數,還可通過插件的回調函數進行一些邏輯注入。就拿上面大家掃碼看到的例子的部分HTML來分析下AlloyTouch.FullPage的使用姿勢:
<div id="fullpage">
<div>
<div>
<div class="animated" data-show="bounceInLeft" data-hide="bounceOutLeft">AlloyTouch Introduction</div>
<div class="animated" data-delay="500" data-show="bounceInUp" data-hide="zoomOut"><img src="asset/alloytouch.png"></div>
<div class="animated" data-delay="1200" data-show="bounceIn" data-hide="bounceOut">By AlloyTeam</div>
</div>
</div>
<div>
<div>
<div class="animated" data-delay="100" data-show="flipInY" data-hide="flipOutY" >Powerful Features</div>
<div class="animated" data-delay="400" data-show="zoomIn" data-hide="zoomOut"><img src="asset/power.png"></div>
</div>
</div>
...
...
...
</div>
注意,上面只是部分HTML,而且我已經把一些和插件配置無關的HTML去掉了。下面一一進行分析:
- class="animated"符合animate.css的約定,加上了這個class代表會有動畫。
- data-delay代表滾到該頁面之后,被標記的DOM元素要等待多久才開始播放動畫。如果開發者不標記的話默認值是0。
- data-show代表被標記的DOM元素顯示的動畫類型
- data-hide代表被標記的DOM元素隱藏的動畫類型(這個通常用戶看不到,但是為了show的時候平滑,一般設置為與data-show的相反的類型)
就這么多,配置就這么多,配置就這么多!!夠簡單把!!
當然你需要在js里面初始化一下:
new AlloyTouch.FullPage("#fullpage",{
animationEnd:function () {
},
leavePage: function (index) {
console.log("leave"+index)
},
beginToPage: function (index) {
console.log("to"+index);
pb.to(index / (this.length-1));
}
});
- animationEnd是滾動結束之后的回調函數
- leavePage是代表離開某個頁面的回調函數
- beginToPage代表打算去某個頁面的回調函數
上面的pb是用來設置nav或者progress的進度,這個可以先不用管。如果有需要的話,用戶可以自己封裝任意的進度條組件。
原理分析
這里主要抽取了AlloyTouch.FullPage的核心代碼進行分析:
new AlloyTouch({
touch: this.parent,
target: this.parent,
property: "translateY",
min: (1 - this.length) * this.stepHeight,
max: 0,
step: this.stepHeight,
inertia: false,
bindSelf : true,
touchEnd: function (evt, v, index) {
var step_v = index * this.step * -1;
var dx = v - step_v;
if (v < this.min) {
this.to(this.min);
} else if (v > this.max) {
this.to(this.max);
} else if (Math.abs(dx) < 30) {
this.to(step_v);
}else if (dx > 0) {
self.prev();
} else {
self.next();
}
return false;
},
animationEnd: function () {
option.animationEnd.apply(this,arguments);
self.moving = false;
}
});
- 這里觸摸和運動的Dom都是fullpage的dom,也就是上面的this.parent
- 因為是上下滾動,所以運動的屬性是translateY
- min可以通過window.innerHeight和總共的頁數推算出來,this.stepHeight就是window.innerHeight
- max顯然就是0
- step顯然就是window.innerHeight,也就是this.stepHeight
- inertia: false代表把慣性運動禁止掉,也就是用戶松手和不會慣性滾動
- bindSelf是意思是touchmove和touchend以及touchcancel都綁定在this.parent自己,而非window下。不設置bindSelf的話touchmove和touchend以及touchcancel都綁定在window下。
這里需要特別詳細說下,這個bindSelf配置非常有用,比如很典型的應用場景就是解決AlloyTouch嵌套AlloyTouch的問題。比如你上面掃碼看到的例子里面,嵌套了AlloyTouch的Demo如下所示:
這里其實是嵌套的滾動。滾動里面的會導致外面的也滾動?怎么解決?里面的滾動必須加上bindSelf並且阻止冒泡:
且看內部滾動的詳細代碼:
var scroller = document.querySelector("#scroller");
Transform(scroller,true);
new AlloyTouch({
touch:"#demo0",
target: scroller,
property: "translateY",
min:250-2000,
max: 0 ,
touchStart:function(evt){
evt.stopPropagation();
},
touchMove:function(evt){
evt.stopPropagation();
},
bindSelf:true
})
這樣的話,嵌套的HTML里面的嵌套的AlloyTouch就不會向上冒泡了,也就是滾動里面的就不會觸發外面的滾動。
繼續分析FullPage源碼:
touchEnd是用戶手指離開屏幕之后的回調函數。里面有邊界處理的邏輯:
- 超出min和max都會對應的校正會min和max。
- step校正,絕對值小於30px會復位
- step校正,絕對值大於30px且大於0會去上一頁
- step校正,絕對值大於30px且小於0會去下一頁
- return false代表不會去運行AlloyTouch松開手后的運動校正邏輯,這點很重要
animationEnd就是運動結束之后的回調函數,會去執行用戶從AlloyTouch.FullPage傳遞過來的animationEnd,並且把moving設置為false
開啟AlloyTouch.FullPage之旅
Github:https://github.com/AlloyTeam/AlloyTouch
任何意見和建議歡迎new issue,我們會第一時間反饋。