ScrollTrigger是利用滑鼠滾動來控制動畫的套件,最大的賣點之一是他可以做出pin的效果,你可以自由控制什麼時候要被pin住。
ScrollTrigger 的基礎操作
ScrollTrigger是利用滑鼠滾動來控制動畫的套件,最大的賣點之一是他可以做出pin的效果,你可以自由控制什麼時候要被pin住。
他的原理是fixed住你想pin的區塊並且加入padding-bottom
把下方的區塊推下去,讓使用者在感覺不出來畫面是有真實在滾動的。
step 1. 載入套件
第一步你要先告訴gsap你要加載這個套件跟你要控制的物件
gsap.registerPlugin(ScrollTrigger); |
step 2. 設定開始跟結束的範圍&動畫效果
第二步你要設定開始點跟結束點,如果你覺得觸發的條件有點抽象可以開啟markers檢視觸發的位置在哪裡。觸發的點是當scroller-start進入start時開始,scroller-end進入到end時結束
gsap.to(".b", { |
常見參數介紹
指令 | 型別 | 用途 |
---|---|---|
start | String | Number | Function |
|
end | String | Number | Function |
|
markers | Boolean | 打開位置檢查器 |
horizontal | Boolean | 打開的話往下畫面會橫向移動(可以開啟markers發現位置由上下變成左右了) |
pin | Boolean | Element | 觸發時會被釘選住(fixed),參數也可以設定你想pin的元素位置 |
pinSpacing | Boolean | 如果不想要釘選時自動生成下方的padding,可以使用false取消掉 |
toggleClass | String | 觸發時該物件會新增的class,class名稱須為字串(如果你想新增class的地方不是該物件就只能用onEnter的方法觸發) |
toggleActions | String | 需要輸入四個參數,分別代表onEnter、onLeave、onEnterBack、onLeaveBack的行爲(EX:play none none none 代表只有正向進入時會執行動畫) |
scrub | Boolean | Number | 如果設定true代表會按照滑鼠滾動的距離計算動畫的位置,如果設定數字則代表動畫延遲的秒數 |
onEnter | Function | 由上往下進入時觸發函式 onEnter: () => {...} |
onEnterBack | Function | 由下往上進入時觸發函式 onEnterBack: () => {...} |
onLeave | Function | 由上往下離開時觸發程式 onLeave: () => {...} |
onLeaveBack | Function | 由下往上離開時觸發函式 onLeaveBack: () => {...} |
註:這些參數都必須寫在scrollTrigger裡面才會作用
如果覺得onEnter很抽象的話,官方也有給解釋的範例
更詳細的參數介紹請見官方手冊
使用timeline優化流程
上述的範例都是在物件只有一個的情況下,當你的動畫是由很多物件組合在一起的,這時使用timeline去組合這些動畫會比較好。
step 1. 設定 timeline
首先你要先建立一個gsap.timeline
,trigger的位置是這些物件的父層容器。
gsap.registerPlugin("ScrollTrigger"); |
看下面的範例可以發現只要放在父層容器的所有物件都會跟著被fixed住,直到滾動超過2000px後才恢復正常的效果。
step 2. 設定動畫的時間軸
就像接龍一樣把接下來想做的動畫串連上去就可以了。
gsap.timeline({ |
如果你覺得接龍的方式會讓函式變得一大串,也可以把它拆分成多段,這樣程式碼看起來就不會像一坨義大利麵。
let part1_tl = gsap.timeline(); |
案例研究
我這邊分析幾個官方給的example,可以從中學習他們是如何運用這些參數去做動畫。
案例一 stagger的運用
stagger是用來處理多個物件時每一個物件的間距秒數
首先他把大砲跟射出去的東西拆成兩個timeline,再用一個masterTl去組合在一起。
const masterTl = gsap.timeline({ |
大砲的部分,他用3段動畫組合在一起,分別是往左、左右搖擺、往右,因為沒有設定scrollTrigger所以動畫會是一個執行完馬上接著做下一個。
const tl1 = gsap |
子彈的部分因為是一個一個射出去,所以你要給gsap一個array讓他知道要抓取哪些元素。
const bullets = []; |
tip
gsap.utils()
是gsap提供的一些實用的方法,你不一定要用原生的JS去處理,這邊有相關的方法介紹。
所以按照文件說明 gsap.utils.random(2, 35, 1)
這段的意思就是隨機產生2~35的數字寫最小單位是1(也就是不會有小數點)
tip
gsap.set()
是設定元素的css設定需要有兩個參數,第一個是作用的元素、第二個是css樣式,等同於沒有ease效果的gsap.to()。
gsap.set(".class", { x: 100, y: 50, opacity: 0 }); // 這兩個的結果會一樣
gsap.to(".class", { duration: 0, x: 100, y: 50, opacity: 0 });
gsap.set([obj1, obj2, obj3], { x: 100, y: 50, opacity: 0 }); // 第一個參數也可以為array
最後做出 1.子彈出現 2.子彈射出 的連續動畫,這邊有用到physics2D
這個是需要付費的套件功能(Physics2DPlugin),所以就不多作介紹。
const tl2 = gsap |
案例二 橫向移動
當你要介紹timeline相關的內容時,橫向移動是一個非常好的呈現方式
首先你要先抓取你要橫向移動的區塊,並且計算它有多長
let pinWrap = document.querySelector(".pin-wrap"); |
接著使用scrollTrigger把畫面固定住並且給他需要橫向移動的長度(這邊把ease關掉估計是怕locomotive-scroll會互相干擾)
gsap.to(".pin-wrap", { |
最後因為他有使用locomotive-scroll的關係,所以有使用refresh()跟update()的方式防止scrollTrigger計算錯誤。
進階設定
這邊舉一些我有用過的參數或是屬性,因為實在太多了無法一一列舉。
偵測裝置行為
有時候你會遇到手機裝置跟滑鼠裝置做出不一樣的行為時可以使用ScrollTrigger.isTouch
這個屬性去做判斷。
0為滑鼠模式,1為觸碰模式,2為兩者皆是
if (ScrollTrigger.isTouch) { |
偵測移動方向
當你需要判斷現在使用者是往哪裡滑動的時候,可以用ScrollTrigger.observe()
去做偵測不需要另外使用Observer這個套件。
至於參數設定跟Observer一樣,會在下一篇做更詳細的介紹。
ScrollTrigger.observe({ |
同時控制多個相同的動畫
一般來說你可以用ScrollTrigger.array()
同時控制多個物件,這邊有提供一個ScrollTrigger.batch()
讓你更簡便處理回調函式。