1. 事前準備
捲動驅動的動畫,可根據捲動容器的捲動位置控制動畫的播放。也就是說,當您向上或向下捲動時,動畫會向前或向後滑動。此外,透過捲動式動畫,您也可以根據元素在捲動容器中的位置控制動畫。這可讓你建立有趣的效果,例如視差背景圖片、捲動進度列,以及會在進入檢視畫面時顯示的圖片。
Chrome 115 的新功能支援一組 JavaScript 類別和 CSS 屬性,可讓您輕鬆建立宣告式捲動驅動動畫。這些新的 API 可與現有的 Web Animations 和 CSS Animations API 搭配使用。
本程式碼研究室將說明如何使用 CSS 建立捲動導向的動畫。完成本程式碼研究室後,您將熟悉這項令人期待功能導入的多項全新 CSS 屬性,例如 scroll-timeline
、view-timeline
、animation-timeline
和 animation-range
。
課程內容
- 如何在 CSS 中使用捲動時間軸建立視差背景效果。
- 如何在 CSS 中使用捲動時間軸建立進度列。
- 如何使用 CSS 中的檢視畫面時間軸功能製作圖片顯示效果。
- 如何在 CSS 中指定不同類型的檢視畫面時間軸範圍。
軟硬體需求
請準備下列其中一組裝置:
- ChromeOS、macOS 或 Windows 上的最新版 Chrome(115 以上版本),並提供「實驗性 Web Platform 功能」旗標已設為 enabled
- 基本的 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
動畫加入主體元素。其 animation-duration
屬性設為 1 秒,並使用 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);
}
由於根捲動器也是最靠近主體元素的父項捲動器,因此您也可以使用 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
採用絕對位置,因此決定其位置的第一個父項元素是套用 position: relative
的 .gallery
元素。也就是說,系統不會在進行自動查詢時考量 .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-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
主要畫面格會套用至 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 大會)