之前做官網,設計的交互雖然在其他網站很常見,但是我一時不知道如何實現,直到我看到了gsap,發現原來這么簡單。
- demo地址: https://3qmjbvapps2o60q4lto2hwpu4whh0zp1iefvt40hypsf1mxaf9.walrus.site/
- 源碼地址:https://github.com/klren0312/gsap-demo
項目搭建
1. 創建vite項目,并安裝依賴
# 創建一個原生ts項目
pnpm create vite gsap-demo --template vanilla-ts
cd gsap-demo
# 安裝gsap依賴
pnpm add gsap
2. 初始化gsap
import { gsap } from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'
gsap.registerPlugin(ScrollTrigger)
效果一:橫向滾動
滾動頁面滾動條,gsap會接管滾動條,進行div的橫向滾動。
image.png
1. 編寫html
父組件flex布局,子元素設置三個圖片。
<div class="box-container">
<div class="box">
<img class="box-image" src="https://picsum.photos/1200/900" alt="box" />
</div>
<div class="box">
<img class="box-image" src="https://picsum.photos/1200/900" alt="box" />
</div>
<div class="box">
<img class="box-image" src="https://picsum.photos/1200/900" alt="box" />
</div>
</div>
.box-container {
display: flex;
flex-wrap: nowrap;
gap: 20px;
overflow: hidden;
}
.box {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100vh;
flex-shrink: 0;
}
.box-image {
object-fit: cover;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
border-radius: 10px;
}
2. 配置gsap
const boxContainer: HTMLElement | null = document.querySelector('.box-container')
const boxItems = gsap.utils.toArray('.box-container .box')
if (!boxContainer) return
gsap.to(boxItems, {
xPercent: -100 * (boxItems.length - 1),
ease: 'none',
scrollTrigger: {
trigger: boxContainer,
pin: true,
start: 'top top',
scrub: 1,
markers: true,
end: `+=${boxContainer.offsetWidth || 0 - innerWidth}`,
},
})
詳細說明:
-
xPercent
: -100 (boxItems.length - 1): 這行代碼設置了每個 boxItems 元素的水平移動百分比。xPercent 是一個相對移動的值,-100 (boxItems.length - 1) 意味著將所有的 boxItems 元素水平移動到最后一個元素的位置。 -
ease: 'none'
: 這里設置了動畫的緩動效果為“無”,即動畫將以線性方式進行,沒有加速或減速。 -
scrollTrigger
: 這是 ScrollTrigger 插件的配置對象,用于定義滾動觸發的行為。-
trigger: boxContainer
: 指定哪個元素觸發滾動動畫。 -
pin: true
: 將 boxContainer 固定在視口中,直到動畫結束。 -
start: 'top top'
: 定義動畫開始的滾動位置,當 boxContainer 的頂部與視口頂部對齊時開始。 -
scrub: 1
: 使動畫與滾動同步,值為 1 表示動畫的平滑度。 -
markers
: true: 顯示滾動觸發器的標記,方便調試。 -
end: +=${boxContainer.offsetWidth || 0 - innerWidth}
: 定義動畫結束的滾動位置,計算方式是 boxContainer 的寬度減去視口的寬度。這段代碼的目的是在用戶滾動頁面時,創建一個水平滾動的動畫效果,使得 boxItems 元素在 boxContainer 內水平移動。
-
3. 查看效果
設置了的start: 'top top'
后,可以看到marker的scroller-start
和scroller-end
都在視口的頂部。
當marker的start
移動到scroller-start
后則開始動畫。
image.png
當marker的end
移動到scroller-end
后則結束動畫
image.png
效果二:卡片效果
滾動頁面,卡片從右往左展示,類似卡片切換效果。
image.png
1. 編寫html
絕對定位card,讓他們交錯排布。
<div class="card-container">
<div class="card card-1">
<img class="card-image" src="https://picsum.photos/400/300" alt="card" />
</div>
<div class="card card-2">
<img class="card-image" src="https://picsum.photos/400/300" alt="card" />
</div>
<div class="card card-3">
<img class="card-image" src="https://picsum.photos/400/300" alt="card" />
</div>
<div class="card card-4">
<img class="card-image" src="https://picsum.photos/400/300" alt="card" />
</div>
<div class="card card-5">
<img class="card-image" src="https://picsum.photos/400/300" alt="card" />
</div>
</div>
.card-container {
position: relative;
display: flex;
flex-wrap: nowrap;
gap: 20px;
overflow: hidden;
width: 100%;
height: 100vh;
}
.card {
width: 400px;
height: 300px;
position: absolute;
top: 50%;
transform: translateY(-50%);
flex-shrink: 0;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
border-radius: 10px;
border: 2px solid #ccc;
overflow: hidden;
}
.card-1 {
right: 10%;
}
.card-2 {
right: 12%;
}
.card-3 {
right: 14%;
}
.card-4 {
right: 16%;
}
.card-5 {
right: 18%;
}
2. 編寫gsap動畫
const cardContainer: HTMLElement | null = document.querySelector('.card-container')
if (!cardContainer) return
gsap.timeline({
scrollTrigger: {
trigger: cardContainer,
pin: true,
start: 'top top',
scrub: 1,
end: `+=${cardContainer.offsetWidth || 0 - innerWidth}`,
markers: true,
},
})
.to('.card-5', { xPercent: -110, scale: 1.1 }, 0)
.to('.card-5', { xPercent: -250, scale: 1 }, 1)
.to('.card-4', { xPercent: -110, scale: 1.1 }, 1)
.to('.card-4', { xPercent: -250, scale: 1 }, 2)
.to('.card-3', { xPercent: -110, scale: 1.1 }, 2)
.to('.card-3', { xPercent: -250, scale: 1 }, 3)
.to('.card-2', { xPercent: -110, scale: 1.1 }, 3)
.to('.card-2', { xPercent: -250, scale: 1 }, 4)
.to('.card-1', { xPercent: -110, scale: 1.1 }, 4)
.to('.card-1', { xPercent: -250, scale: 1 }, 5)
詳細說明:
-
gsap.timeline
: 創建一個時間軸動畫,允許多個動畫按順序執行 -
gsap.timeline.to
: 創建每個時間點的動畫詳情,例如本效果,就是每個卡片向左移動一定百分比和放大縮小效果。
3.查看效果
主要就是最后右邊移動到中間并放大,然后移動到最左邊縮小到正常大小,每個card依次執行。
image.png
總結
主要還是要多看文檔,然后通過makers來確定滾動位置是否正確。尤其是結合整個頁面時,要保證頁面的高度時刻確定的,這樣才能讓頁面加載完畢后,gsap的makers計算正確,比如之前設置了圖片懶加載,但是忘了設置圖片的高度,導致下面的gsap計算錯誤,滾動效果出現問題,這個時候就需要開啟markers來確定問題。
參考文檔
-
gsap.to
: https://gsap.com/docs/v3/GSAP/gsap.to() -
gsap.timeline
: https://gsap.com/docs/v3/GSAP/Timeline -
gsap.timeline.to
: https://gsap.com/docs/v3/GSAP/Timeline/to()