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 時間軸建立圖片顯示效果。
- 如何在 CSS 中指定不同類型的觀看歷程時間範圍。
軟硬體需求
請準備下列其中一組裝置:
- 在 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% 開始增加,直到下滑條滑到底為止。
查看進度時間軸
這類時間軸會連結至捲動容器中特定元素的相對進度。就像捲動進度時間軸一樣,系統會追蹤捲軸的捲動偏移量。與捲動進度時間軸不同,此時間軸會根據主體在捲動器中的相對位置決定進度。這與 IntersectionObserver
相似,後者會追蹤元素在捲動器中顯示的比例。如果元素在捲軸中沒有顯示,表示兩者並未重疊。如果在捲軸中顯示,即使是最小的部分也是如此,就表示兩者重疊。
檢視進度時間軸會從主體開始與捲動條交錯的瞬間開始,並在主體停止與捲動條交錯時結束。請注意,在下方示意圖中,當主體進入捲動容器時,進度會從 0% 開始計數,並在主體離開捲動容器時達到 100%。
根據預設,連結至「View Progress」時間軸的動畫會連結至整個時間軸範圍。從主體進入捲動區的瞬間開始,到主體離開捲動區為止。
您也可以指定要附加的範圍,將其連結至「觀看進度時間軸」的特定部分。例如,只有在主體進入捲軸時才會發生這種情況。在下列示意圖中,當主體進入捲動容器時,進度會從 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%;
}
}
- 現在,請將這些主要畫面格附加至 body 元素:
src/styles.css
body {
animation: 1s linear move-background;
}
透過這段程式碼,系統會將 move-background
動畫新增至 body 元素。其 animation-duration
屬性設為 1 秒,並使用 linear
緩動效果。
使用匿名捲動進度時間軸,將動畫連結至根目錄的捲動進度
建立捲動進度時間軸最簡單的方法,就是使用 scroll()
函式。這會建立匿名捲動進度時間軸,您可以將其設為 animation-timeline
屬性的值。
scroll()
函式可接受 <scroller>
和 <axis>
引數。
<scroller>
引數可接受的值如下:
nearest
:使用最近的祖系捲動容器 (預設)。root
:使用文件檢視區做為捲動容器。self
:使用元素本身做為捲動容器。
<axis>
引數可接受的值如下:
block
:沿著捲動容器的區塊軸測量進度 (預設)。inline
:沿著捲動容器內嵌軸測量進度。y
:沿著捲動容器的 y 軸測量進度。x
:沿著捲動容器的 x 軸測量進度。
如要將動畫連結至區塊軸上的根捲動器,請將 root
和 block
傳遞至 scroll()
。將這些值組合起來,即可得到 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);
}
由於根捲動器恰好也是主體元素最近的父捲動器,您也可以使用 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
元素上建立名為 Scroll Progress Timeline 的時間軸,然後使用該名稱將 .gallery__progress
連結至該時間軸。
建立並連結命名的捲動進度時間軸
如要在元素上建立名為「Scroll Progress Timeline」的時間軸,請將捲動容器上的 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 Progress 時間軸
您可以加入一個不錯的效果,讓圖庫圖片在顯示時淡入。您可以使用「View Progress Timeline」(檢視進度時間軸) 來達成這項目標。
如要建立 View Progress Timeline,您可以使用 view()
函式。可接受的引數為 <axis>
和 <view-timeline-inset>
。
<axis>
與捲動進度時間軸相同,可定義要追蹤的軸。- 使用
<view-timeline-inset>
時,您可以指定偏移值 (正值或負值),藉此調整元素是否在檢視區域內的邊界。
- 關鍵影格已就定位,您只需附加即可。如要這麼做,請在每個
.gallery__entry
元素上建立 View Progress Timeline。
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);
}
限制 View Progress 時間軸的範圍
如果您儲存 CSS 並載入網頁,您會看到元素淡入,但似乎有點不對勁。當元素完全離開畫面時,它們會從不透明度 0
開始,且只有在完全離開畫面時才會變成不透明度 1
。
這是因為 View Progress Timeline 的預設範圍是完整範圍。這就是 cover
範圍。
- 如要只指定主體的
entry
範圍,請使用animation-range
CSS 屬性,以便限制動畫的執行時機。
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
keyframes 會套用至 entry
範圍,而 animate-out
keyframes 會套用至 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 中建立捲動進度時間軸和檢視進度時間軸!
瞭解詳情
資源:
- 使用捲動驅動動畫為捲動畫面中的元素設定動畫
- 查看時間軸範圍視覺化工具
- Web Animations 的新功能 (Google I/O 2023)