1. 事前準備
捲動驅動動畫可讓您根據捲動容器的捲動位置,控制動畫的播放情形。也就是說,向上或向下捲動時,動畫會向前或向後掃動。此外,您也可以使用捲動驅動動畫,根據元素在捲動容器中的位置控制動畫。您可以藉此建立有趣的特效,例如視差背景圖片、捲動進度列,以及捲動到特定位置時才會顯示的圖片。
Chrome 115 新增支援一組 JavaScript 類別和 CSS 屬性,方便您輕鬆建立宣告式捲動驅動動畫。這些新 API 可與現有的 Web Animations 和 CSS Animations API 搭配使用。
本程式碼研究室會說明如何使用 CSS 建立捲動驅動動畫。完成本程式碼研究室後,您將熟悉這項令人期待的功能所導入的許多新 CSS 屬性,例如 scroll-timeline、view-timeline、animation-timeline 和 animation-range。
課程內容
- 瞭解如何使用 CSS 中的捲動時間軸,建立視差背景效果。
- 如何使用 CSS 中的捲動時間軸建立進度列。
- 如何使用 CSS 中的 View Timeline 建立圖片顯示效果。
- 如何在 CSS 中指定不同類型的 View 時間軸範圍。
軟硬體需求
請準備下列其中一組裝置:
- 在 ChromeOS、macOS 或 Windows 上使用最新版 Chrome (115 以上版本),並將「Experimental Web Platform Features」旗標設為啟用。
- 對 HTML 有基本瞭解
- 對 CSS 有基本瞭解,尤其是 CSS 中的動畫
2. 做好準備
本專案所需的一切內容都放在 GitHub 存放區中。如要開始使用,請複製程式碼,然後在您慣用的開發環境中開啟。
- 開啟新的瀏覽器分頁,然後前往 https://github.com/googlechromelabs/io23-scroll-driven-animations-codelab。
- 複製存放區。
- 在想用的 IDE 中開啟程式碼。
- 執行
npm install安裝依附元件。 - 執行
npm start並前往 http://localhost:3000/。 - 或者,如果沒有安裝 npm,請在 Chrome 中開啟
src/index.html檔案。
3. 瞭解動畫時間軸
根據預設,附加至元素的動畫會在文件時間軸上執行。也就是說,網頁載入時,動畫會隨著時間推進。這是預設動畫時間軸,也是您目前唯一可存取的動畫時間軸。
使用捲動驅動動畫時,您會取得兩種新的時間軸:
- 捲動進度時間軸
- 查看進度時間軸
在 CSS 中,可以使用 animation-timeline 屬性將這些時間軸附加至動畫。請參閱下文,瞭解這些新時間表代表的意義,以及彼此間的差異。
捲動進度時間軸
捲動進度時間軸是動畫時間軸,會連結至捲動容器 (也稱為捲動埠或捲動器) 沿特定軸的捲動位置進度。這項函式會將捲動範圍中的位置轉換為時間軸的進度百分比。
開始捲動位置代表 0% 的進度,結束捲動位置則代表 100% 的進度。在下方的視覺化效果中,請注意,當您向下捲動捲軸時,進度會從 0% 增加到 100%。
查看進度時間軸
這類時間軸會連結至捲動容器中特定元素的相對進度。與捲動進度時間軸類似,系統會追蹤捲動器的捲動偏移。與捲動進度時間軸不同,進度取決於主體在捲動器中的相對位置。這與 IntersectionObserver 類似,可追蹤元素在捲軸中的顯示程度。如果元素在捲動器中不可見,則不會相交。如果可捲動容器內顯示該元素 (即使只有一小部分),即為相交。
當主體開始與捲軸相交時,系統就會開始計算「查看進度時間軸」,並在主體停止與捲軸相交時結束計算。在下圖中,請注意,當主體進入捲動容器時,進度會從 0% 開始向上計數,並在主體離開捲動容器時達到 100%。
根據預設,連結至「檢視進度時間軸」的動畫會附加至整個範圍。從主體進入捲動檢視區塊開始,到主體離開捲動檢視區塊為止。
您也可以指定要附加的範圍,將其連結至「查看進度時間軸」的特定部分。舉例來說,只有在主體進入捲動器時,在下方的視覺化圖片中,當主體進入捲動容器時,進度會從 0% 開始向上計數,但從完全交集的那一刻起,進度就會達到 100%。
您可以指定下列觀看時間軸範圍:cover、contain、entry、exit、entry-crossing 和 exit-crossing。這些範圍會在程式碼研究室的後續部分說明,但如果您想搶先瞭解,請使用 https://goo.gle/view-timeline-range-tool 的工具,查看每個範圍代表的意義。
4. 建立視差背景效果
要新增至網頁的第一個效果,是主要背景圖片的視差背景效果。向下捲動頁面時,背景圖片應該會移動,但速度不同。為此,您需要使用捲動進度時間軸。
如要實作這項功能,請完成下列兩個步驟:
- 建立動畫,移動背景圖片的位置。
- 將動畫連結至文件的捲動進度。
建立動畫
- 如要建立動畫,請使用一般主要畫面格。在其中,將背景位置從垂直 0% 移至 100%:
src/styles.css
@keyframes move-background {
from {
background-position: 50% 0%;
}
to {
background-position: 50% 100%;
}
}
- 現在,請將這些主要畫面格附加至主體元素:
src/styles.css
body {
animation: 1s linear move-background;
}
使用這段程式碼,即可將 move-background 動畫新增至 body 元素。其 animation-duration 屬性設為一秒,並使用 linear 緩和效果。
使用匿名捲動進度時間軸,將動畫連結至根項目的捲動進度
如要建立捲動進度時間軸,最簡單的方法是使用 scroll() 函式。這會建立匿名捲動進度時間軸,您可以將其設為 animation-timeline 屬性的值。
scroll() 函式會接受 <scroller> 和 <axis> 引數。
<scroller> 引數可接受下列值:
nearest。使用最接近的祖先捲動容器 (預設)。root:使用文件檢視區塊做為捲動容器。self:使用元素本身做為捲動容器。
<axis> 引數可接受下列值:
block:沿著捲動容器的區塊軸測量進度 (預設)。inline。使用捲動容器內嵌軸的進度測量值。y:使用捲動容器 Y 軸的進度測量值。x:使用捲動容器 X 軸的進度測量值。
如要將動畫連結至區塊軸上的根捲軸,要傳遞至 scroll() 的值為 root 和 block。因此值為 scroll(root block)。
- 將
scroll(root block)設為主體上的animation-timeline屬性值。 - 此外,以秒為單位表示
animation-duration並無意義,因此請將時間長度設為auto。如未指定animation-duration,系統會預設為auto。
src/styles.css
body {
animation: linear move-background;
animation-duration: auto;
animation-timeline: scroll(root block);
}
由於根捲軸也是 body 元素最接近的父項捲軸,因此您也可以使用 nearest 值:
src/styles.css
body {
animation: linear move-background;
animation-duration: auto;
animation-timeline: scroll(nearest block);
}
由於 nearest 和 block 是預設值,您甚至可以選擇省略這些值。在這種情況下,程式碼可以簡化為:
src/styles.css
body {
animation: linear move-background;
animation-duration: auto;
animation-timeline: scroll();
}
驗證變更
如果一切順利,您現在應該會看到以下內容:
如果沒有,請查看程式碼的 solution-step-1 分支。
5. 為圖片庫建立進度列
頁面上的水平輪轉介面需要進度列,才能指出目前查看的相片。
輪轉介面的標記如下所示:
src/index.html
<div class="gallery">
<div class="gallery__scrollcontainer" style="--num-images: 3;">
<div class="gallery__progress"></div>
<div class="gallery__entry">
...
</div>
<div class="gallery__entry">
...
</div>
<div class="gallery__entry">
...
</div>
</div>
</div>
進度列的影格已就位,如下所示:
src/styles.css
@keyframes adjust-progress {
from {
transform: scaleX(calc(1 / var(--num-images)));
}
to {
transform: scaleX(1);
}
}
這個動畫必須附加至 。元素,並搭配捲動進度時間軸。gallery__progress如上一個步驟所示,您可以使用 scroll() 函式建立匿名捲動進度時間軸,即可達成此目的:
src/styles.css
.gallery__progress {
animation: linear adjust-progress;
animation-duration: auto;
animation-timeline: scroll(nearest inline);
}
雖然這段程式碼看似可行,但由於使用 nearest 的自動捲動容器查詢方式,因此無法運作。在尋找最近的捲動器時,元素只會考慮可能影響其位置的元素。由於 .gallery__progress 是絕對定位,因此決定其位置的第一個父項元素是 .gallery 元素,因為該元素已套用 position: relative。也就是說,系統在自動查閱時,完全不會考慮 .gallery__scrollcontainer 元素 (需要做為目標的捲動器)。
如要解決這個問題,請在 .gallery__scrollcontainer 元素上建立具名的捲動進度時間軸,並使用該名稱將 .gallery__progress 連結至該時間軸。
建立並連結已命名的捲動進度時間軸
如要在元素上建立具名的捲動進度時間軸,請將捲動容器的 scroll-timeline-name CSS 屬性設為您喜歡的值。值必須以 -- 開頭。
由於圖庫會水平捲動,因此您也需要設定 scroll-timeline-axis 屬性。允許的值與 scroll() 的 <axis> 引數相同。
最後,如要將動畫連結至捲動進度時間軸,請將需要動畫效果的元素上的 animation-timeline 屬性,設為與 scroll-timeline-name 所用 ID 相同的值。
- 變更
styles.css檔案,加入以下內容:
src/styles.css
.gallery__scrollcontainer {
/* Create the gallery-is-scrolling timeline */
scroll-timeline-name: --gallery-is-scrolling;
scroll-timeline-axis: inline;
}
.gallery__progress {
animation: linear adjust-progress;
animation-duration: auto;
/* Set gallery-is-scrolling as the timeline */
animation-timeline: --gallery-is-scrolling;
}
驗證變更
如果一切順利,您現在應該會看到以下內容:
如果沒有,請查看程式碼的 solution-step-2 分支。
6. 在圖片進入和離開捲動檢視區時加入動畫效果
淡入顯示圖片庫中的圖片
設定匿名檢視進度時間軸
建議您新增淡入效果,讓圖片在進入檢視畫面時淡入。如要查看進度,可以使用「查看進度時間軸」。
如要建立「查看進度時間軸」,可以使用 view() 函式。可接受的引數為 <axis> 和 <view-timeline-inset>。
<axis>與捲動進度時間軸中的相同,用於定義要追蹤的軸。- 使用
<view-timeline-inset>時,您可以指定偏移 (正值或負值),在系統判斷元素是否在檢視區塊中時調整界線。
- 關鍵影格已就位,因此您只需要附加即可。如要這麼做,請在每個
.gallery__entry元素上建立「查看進度時間軸」。
src/styles.css
@keyframes animate-in {
from {
opacity: 0;
clip-path: inset(50% 0% 50% 0%);
}
to {
opacity: 1;
clip-path: inset(0% 0% 0% 0%);
}
}
.gallery__entry {
animation: linear animate-in;
animation-duration: auto;
animation-timeline: view(inline);
}
限制「觀看進度時間軸」的範圍
如果您儲存 CSS 並載入網頁,會看到元素淡入,但似乎有問題。元素完全不在檢視區塊中時,不透明度為 0,完全離開檢視區塊時,不透明度才為 1。
這是因為「檢視進度時間軸」的預設範圍是完整範圍。這就是所謂的cover範圍。
- 如要只鎖定主體的
entry範圍,請使用animation-rangeCSS 屬性,限制動畫的執行時間。
src/styles.css
.gallery__entry {
animation: linear fade-in;
animation-duration: auto;
animation-timeline: view(inline);
animation-range: entry 0% entry 100%;
}
動畫現在會從 entry 0% (主體即將進入捲軸) 執行到 entry 100% (主體已完全進入捲軸)。
可用的時間軸範圍如下:
cover。代表檢視進度時間軸的完整範圍。entry:代表主方塊進入檢視畫面進度可見範圍的期間。exit。代表主方塊退出檢視畫面進度顯示範圍的範圍。entry-crossing:代表主方塊跨越結尾邊界邊緣的範圍。exit-crossing。代表主方塊跨越起始邊界邊緣的範圍。contain。代表主方塊完全包含在捲動埠的檢視區塊進度可見度範圍內,或完全涵蓋該範圍的時間範圍。這取決於主體是否高於或低於捲軸。
使用 https://goo.gle/view-timeline-range-tool 的工具,瞭解每個範圍代表的意義,以及百分比如何影響開始和結束位置。
- 由於這裡的開始和結束範圍相同,且使用預設位移,因此請將
animation-range簡化為單一動畫範圍名稱:
src/styles.css
.gallery__entry {
animation: linear animate-in;
animation-duration: auto;
animation-timeline: view(inline);
animation-range: entry;
}
淡出相片庫圖片
- 如要讓圖片在離開捲動器時淡出,請執行與淡入動畫相同的操作,但指定不同的範圍。
src/styles.css
@keyframes animate-out {
from {
opacity: 1;
clip-path: inset(0% 0% 0% 0%);
}
to {
opacity: 0;
clip-path: inset(50% 0% 50% 0%);
}
}
.gallery__entry {
animation: linear animate-in, linear animate-out;
animation-duration: auto;
animation-timeline: view(inline);
animation-range: entry, exit;
}
系統會將 animate-in 主要畫面格套用至 entry 範圍,並將 animate-out 主要畫面格套用至 exit 範圍。
驗證變更
如果一切順利,您現在應該會看到以下內容:
如果沒有,請查看程式碼的 solution-step-3 分支。
7. 使用一組主要畫面格,在圖片進入和離開捲動檢視區時加入動畫效果
一組關鍵影格的案例
您可以建立一組已包含範圍資訊的關鍵影格,不必為不同範圍附加兩個動畫。
關鍵影格的形狀如下所示:
@keyframes keyframes-name {
range-name range-offset {
...
}
range-name range-offset {
...
}
}
- 將淡入和淡出主要畫面格合併,如下所示:
src/styles.css
@keyframes animate-in-and-out {
entry 0% {
opacity: 0;
clip-path: inset(50% 0% 50% 0%);
}
entry 90% {
opacity: 1;
clip-path: inset(0% 0% 0% 0%);
}
exit 10% {
opacity: 1;
clip-path: inset(0% 0% 0% 0%);
}
exit 100% {
opacity: 0;
clip-path: inset(50% 0% 50% 0%);
}
}
- 如果關鍵影格中含有範圍資訊,就不必再另外指定
animation-range。將主要畫面格附加為animation屬性。
src/styles.css
.gallery__entry {
animation: linear animate-in-and-out both;
animation-duration: auto;
animation-timeline: view(inline);
}
驗證變更
如果一切順利,您應該會得到與上一個步驟相同的結果。如果沒有,請查看程式碼的 solution-step-4 分支。
8. 恭喜!
您已完成本程式碼研究室,現在瞭解如何在 CSS 中建立捲動進度時間軸和檢視區塊進度時間軸!
瞭解詳情
資源:
- 使用捲動驅動動畫,在捲動時為元素加上動畫效果
- 查看時間軸範圍視覺化工具
- 網頁動畫的新功能 (2023 年 Google I/O 大會)