使用 GSAP 和 ScrollTrigger 實現RWD的動態效果
隨著時代的演進,PM對於網頁特效的要求越來越高了。最近PM提出需要把使用者卡在頁面某個地方,隨滾動進度把動畫看完才放行的效果。於是我想到可以使用GSAP的scrolltrigger來達成。
隨著時代的演進,PM對於網頁特效的要求越來越高了。最近PM提出需要把使用者卡在頁面某個地方,隨滾動進度把動畫看完才放行的效果。於是我想到可以使用GSAP的scrolltrigger來達成。
範例頁面: AFL4-W133-ADLP 的 Durable Aluminum Die Casting Housing
GSAP
GSAP,全名為 GreenSock Animation Platform,是一個強大且高效的 JavaScript 動畫庫。它提供了一個簡單易用的 API,讓開發者能夠輕鬆創建和控制動畫。GSAP 支援各種不同的動畫類型,包括 CSS 屬性、SVG、DOM 屬性等等。
ScrollTrigger
ScrollTrigger 是 GSAP (GreenSock Animation Platform) 的一個插件,它允許你在滾動頁面時觸發動畫。你可以在滾動到特定的元素或者特定的位置時開始、停止、暫停、恢復、反轉或者調整動畫的速度。
引用GSAP、ScrollTrigger
依照專案性質,可使用cdn或是npm的方式
npm
npm install gsap
註冊GSAP、ScrollTrigger
// index.js
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
CDN
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.4/gsap.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.4/ScrollTrigger.min.js"></script>
註冊GSAP、ScrollTrigger
// index.js
gsap.registerPlugin(ScrollTrigger);
建立TimeLine
GSAP Timeline 用於創建和管理動畫序列。你可以使用它來控制多個動畫的播放順序,包括同時播放、順序播放、延遲播放等。
可以直接在timeline中設定scrolltrigger的邏輯。整體播放的速度取決於scrub、end、以及fromTo function 設定的duration值,基本上end的值越大,動畫的duration就會越久。
let tl = gsap.timeline({
scrollTrigger: {
trigger: ".sec-6", // 滾動到 .sec-6 時觸發
pin: true, // 釘選元素
scrub: 0.9, // 動畫的速度,數字越大越慢
start: "top top", // 當 .sec-6 的 top 與 viewport 的 top 對齊時觸發
end: "+=350%", // 滑動到 .sec-6 的 下方 350% 時觸發
},
});
ScrollTrigger 動畫邏輯
prodStartPos、prodEndPos 是元素的起始位置,為了RWD而將此參數獨立出來,在不同斷點調整起始位置。
fromTo 則是設定目標元素的起始(from)、結束(to)樣式。
"<" 代表跟上一個Tween(fromTo function)同步執行,如果沒有設定則是按照Tween的連鎖接續執行動畫
const sec6Animation = (prodStartPos,prodEndPos) => {
tl.fromTo('.sec-6 .title',{
yPercent: 50
},{
yPercent: 0
})
.fromTo('.sec-6 .prod',{
yPercent: prodStartPos,
opacity: 0,
scale: 1.5,
},{
yPercent: prodEndPos,
opacity: 1,
scale: 1,
},'<')
.fromTo('.sec-6 .icons', {
opacity: 0,
yPercent: 30,
duration: 3
},{
opacity: 1,
yPercent: 0,
})
}
RWD調整元素的起始位置
gsap允許我們客製自己的斷點來執行不同的動畫邏輯
let mm = gsap.matchMedia();
const RWDConfig = {
isMobile: `(max-width: 767px)`,
isTablet: `(min-width: 768px) and (max-width: 991px)`,
isLaptop: `(min-width: 992px) and (max-width: 1199px)`,
isPc: `(min-width: 1200px)`
}
mm.add(RWDConfig,(context) => {
let { isMobile, isTablet, isLaptop, isPc } = context.conditions; // 取得RWDConfig
// 因應不同斷點調整產品的起始位置
if(isMobile) {
sec6Animation(-350, -20);
} else if(isTablet) {
sec6Animation(-200, 100);
} else if(isLaptop) {
sec6Animation(-150, 100);
} else if(isPc) {
sec6Animation(-150, 45);
}
})