amp-animation
說明
定義及顯示動畫。
必要指令碼
<script async custom-element="amp-animation" src="https://cdn.ampproject.org/v0/amp-animation-0.1.js"></script>
支援的版面配置
用法
amp-animation
元件可定義及執行自訂動畫和效果。它仰賴 Web Animations API。
amp-animation
元件會在 JSON 結構中定義動畫。最上層區段會宣告目標元素、執行條件、時間屬性和 keyframes effect (關鍵影格效果),藉此定義整體動畫。整體程序可以包含在 animations
陣列中定義的任意數量的動畫部分。動畫陣列中的動畫部分可以有自己的目標元素、執行條件、時間屬性和關鍵影格效果。
<amp-animation layout="nodisplay"> <script type="application/json"> { "selector": "#target-id", "duration": "1s", "iterations": "4", "fill": "both", "direction": "alternate", "animations": [ { "selector": ".target-class", "easing": "cubic-bezier(0,0,.21,1)", "keyframes": { "transform": "rotate(20deg)" } }, { "delay": "2s", "easing": "cubic-bezier(0,0,.21,1)", "keyframes": { "transform": "rotate(30deg)" } } ] } </script> </amp-animation>
如果動畫使用單一元素和單一關鍵影格效果,則此設定可作為單一動畫定義。
<amp-animation layout="nodisplay"> <script type="application/json"> { "selector": "#target-id", "duration": "1s", "keyframes": {"opacity": 1} } </script> </amp-animation>
如果動畫使用多個元素,但沒有最上層動畫,則此設定可作為定義陣列。
<amp-animation layout="nodisplay"> <script type="application/json"> [ { "selector": ".target1", "duration": 1000, "keyframes": {"opacity": 1} }, { "selector": ".target2", "duration": 600, "delay": 400, "keyframes": {"transform": "scale(2)"} } ] </script> </amp-animation>
透過 trigger
屬性或 action (動作) 觸發一個或多個動畫的開始。
您可以將透過動作控制的 amp-animation
放置在 DOM 中的任何位置。如果動畫包含 trigger="visibility"
,則會在父項元素進入可視區域時觸發,並在離開可視區域時暫停。
定義效果
關鍵影格
您必須宣告效果為關鍵影格,才能使用 amp-animations
套用動畫。
您可以在 amp-animation 中以與 MDN 的 Keyframe Formats (關鍵影格格式) 中定義的相同方式指定關鍵影格。您也可以參考在 <style amp-custom>
或 <style amp-keyframes>
標記中定義為 CSS 的 @keyframes
名稱。
以下是一些典型的關鍵影格定義範例。
速記物件格式 "to" 格式指定 100% 的最終狀態
{ "keyframes": {"opacity": 0, "transform": "scale(2)"} }
速記物件格式 "from-to" 格式指定 0% 和 100% 的開始和最終狀態
{ "keyframes": { "opacity": [1, 0], "transform": ["scale(1)", "scale(2)"] } }
速記物件格式 "value-array" 格式指定開始、最終狀態和多個 (等間隔) 位移的多個值
{ "keyframes": { "opacity": [1, 0.1, 0], "transform": ["scale(1)", "scale(1.1)", "scale(2)"] } }
陣列格式指定關鍵影格。位移會自動指派為 0%、100% 和介於兩者之間的均勻間隔
{ "keyframes": [ {"opacity": 1, "transform": "scale(1)"}, {"opacity": 0, "transform": "scale(2)"} ] }
陣列格式也可以明確包含 "offset"
{ "keyframes": [ {"opacity": 1, "transform": "scale(1)"}, {"offset": 0.1, "opacity": 0.1, "transform": "scale(2)"}, {"opacity": 0, "transform": "scale(3)"} ] }
陣列格式也可以包含 "easing"
{ "keyframes": [ {"easing": "ease-out", "opacity": 1, "transform": "scale(1)"}, {"opacity": 0, "transform": "scale(2)"} ] }
使用 @keyframes
CSS 規則
<style amp-custom> @keyframes keyframes1 { from { opacity: 0; } to { opacity: 1; } } </style> <amp-animation layout="nodisplay"> <script type="application/json"> { "duration": "1s", "keyframes": "keyframes1" } </script> </amp-animation>
大多數 CSS @keyframes
符合 Web Animations 規格中的 JSON 內嵌關鍵影格定義,但有以下細微差異
-
您可能需要供應商前置字首,例如
@-ms-keyframes {}
或-moz-transform
,以獲得廣泛的平台支援。JSON 格式不需要且不允許供應商前置字首,但在 CSS 中可能需要。 -
在不支援的平台上,當搭配 CSS 中指定的關鍵影格使用
calc()
和var()
時,amp-animation
的 Polyfills 會失敗。在 CSS 中使用回溯值以避免這種情況。 -
CSS 擴充功能 (例如
width()
、height()
、x()
、y()
、num()
、rand()
、index()
和length()
) 不適用於@keyframes
。
關於 prefers-reduced-motion
通常,執行動畫會將元素置於可見狀態來完成,而初始 CSS 會隱藏元素,以便稍後依賴動畫完成。
使用者可以將其裝置設定為使用減少的動畫。使用此選項時,動畫根本不會執行。在這種情況下,您需要停用稍後依賴動畫執行的 CSS 屬性。
您可以將媒體查詢用於此目的。在以下範例中,<amp-animation>
稍後會透過設定 opacity: 1
將元素動畫化為可見狀態。當動畫停用時,元素始終可見
<style amp-custom> .my-hidden-element { opacity: 1; } @media not (prefers-reduced-motion) { .my-hidden-element { opacity: 0; } } </style> <amp-animation layout="nodisplay"> <script type="application/json"> [ { "selector": ".my-hidden-element", "duration": "1s", "keyframes": {"opacity": 1} } ] </script> </amp-animation>
關鍵影格的允許屬性
amp-animation 元件會限制允許使用的 CSS 屬性,以最佳化效能。以下是允許清單中的屬性
opacity (不透明度)
transform (變形)
visibility (可見性)
offset-distance (位移距離)
clip-path
。僅支援的值為inset()
、circle()
、ellipse()
和polygon()
。
不需要也不允許使用供應商前置字首 CSS 屬性。
時間屬性
最上層動畫和動畫元件可能包含時間屬性。以下是允許的屬性集
屬性 | 類型 | 預設值 | 說明 |
---|---|---|---|
duration (持續時間) | time (時間) | 0 | 動畫持續時間。數值 (以毫秒為單位) 或 CSS 時間值,例如 2s 。 |
delay (延遲) | time (時間) | 0 | 動畫開始執行前的延遲時間。數值 (以毫秒為單位) 或 CSS 時間值,例如 2s 。 |
endDelay (結束延遲) | time (時間) | 0 | 動畫完成後且實際視為完成前的延遲時間。數值 (以毫秒為單位) 或 CSS 時間值,例如 2s 。 |
iterations (迭代次數) | 數字或 "Infinity" 或 "infinite" | 1 | 動畫效果重複的次數。 |
iterationStart (迭代開始) | 數字/CSS | 0 | 效果開始動畫化的時間位移。 |
easing (緩和) | 字串 | "linear" | 用於縮放時間以產生緩和效果的時間函數。 |
direction (方向) | 字串 | "normal" | "normal"、"reverse"、"alternate" 或 "alternate-reverse" 其中之一。 |
fill (填滿) | 字串 | "none" | "none"、"forwards"、"backwards"、"both"、"auto" 其中之一。 |
所有時間屬性都允許直接數值/字串值或 CSS 值。例如,1000
或 1s
或 1000m
都是 duration
的有效值。
JSON 中時間屬性的範例
{ ... "duration": "1s", "delay": 100, "easing": "ease-in", "fill": "both" ... }
動畫元件會繼承為最上層動畫指定的時間屬性。
變數與計算運算式
amp-animation
允許將 var()
、calc()
、min()
和 max()
運算式用於時間和關鍵影格值。
<amp-animation layout="nodisplay"> <script type="application/json"> [ { "selector": ".target-class", "duration": "4s", "delay": "var(--delay)", "--y": "var(--other-y, 100px)", "keyframes": {"transform": "translate(calc(100vh + 20px), var(--y))"} } ] </script> </amp-animation>
您可以宣告 CSS 變數,以透過 var()
運算式用於時間和關鍵影格值。
CSS 變數可用於巢狀動畫,但巢狀動畫可能會覆寫變數的值。
<amp-animation layout="nodisplay"> <script type="application/json"> { "--delay": "0.5s", "--x": "100px", "animations": [ { "selector": "#target1", "delay": "var(--delay)", "--x": "150px", "keyframes": {"transform": "translate(var(--x), var(--y, 0px)"} }, ... ] } </script> </amp-animation>
在以上範例中
-
巢狀動畫會將變數
--delay
套用至#target1
動畫的延遲時間。 -
雖然
--x
會傳播到巢狀動畫中,但會被覆寫。最終的 translate 值為150px
。 -
<amp-animation>
元件中未在任何位置指定--y
。如果查詢找不到定義為<amp style-custom>
標記中的 CSS,則預設為0px
。
Polyfills 同時適用於支援平台上的 var()
和 calc()
。最佳做法是為 var()
包含預設值。
<amp-animation layout="nodisplay"> <script type="application/json"> [ { "selector": ".target-class", "duration": "4s", "delay": "var(--delay, 100ms)" } ] </script> </amp-animation>
透過使用 amp-animation
元件中的 --var-name
欄位,覆寫在 <style amp-custom>
標記中指定的目標元素的變數。var()
運算式會先嘗試解析在動畫元件中指定的值,然後解析目標樣式。
CSS 擴充功能
amp-animation
元件提供以下 CSS 擴充功能:rand()
、num()
、width()
、height()
、x()
和 y()
。允許的 CSS 擴充功能在 amp-animation
定義中可使用 CSS 值的所有位置都有效。這包括時間和關鍵影格值。
CSS index()
擴充功能
index()
函數會傳回動畫效果中目前目標元素的索引。當使用 selector
屬性為多個目標動畫化相同效果時,這最為相關。selector
比對到的第一個目標將具有 index 0
,第二個目標將具有 index 1
,依此類推。
除了其他用途外,此屬性還可以與 calc()
運算式結合以建立交錯效果。例如
{ "selector": ".class-x", "delay": "calc(200ms * index())" }
CSS length()
擴充功能
length()
函數會傳回動畫效果中目標元素的數量。這在與 index()
結合時最為相關
{ "selector": ".class-x", "delay": "calc(200ms * (length() - index()))" }
CSS rand()
擴充功能
rand()
函數會傳回隨機 CSS 值。有兩種形式。
不帶引數的形式會傳回介於 0 和 1 之間的隨機數字。
{ "delay": "calc(10s * rand())" }
第二種形式有兩個引數,並傳回介於這兩個引數之間的隨機值。
{ "delay": "rand(5s, 10s)" }
CSS width()
、height()
、x()
和 y()
擴充功能
width()
/height()
和 x()
/y()
擴充功能會傳回動畫元素或選取器指定的元素的大小或座標。傳回的值以像素為單位,例如 100px
。
amp-animation
支援以下形式
-
width()
、height()
、x()
、y()
- 動畫元素的寬度/高度或座標。 -
使用選取器,例如
width('.selector')
或x('.selector')
- 選取器指定的元素的尺寸或座標。可以使用任何 CSS 選取器。例如,height('#container > li')
。 -
使用最接近的選取器,例如
height(closest('.selector'))
或y(closest('.selector'))
- 最接近的選取器指定的元素的尺寸或座標。
width()
和 height()
對於變形特別有用。left
、top
和類似的 CSS 屬性可以使用 %
值來表示與容器大小成比例的動畫。但是,transform
屬性會以不同的方式解譯 %
值 - 作為所選元素的百分比。因此,width()
和 height()
可用於以容器元素等表示變形動畫。
這些函數可以與 calc()
、var()
和其他 CSS 運算式結合。例如
{ "transform": "translateX(calc(width('#container') + 10px))" }
CSS num()
擴充功能
num()
函數會傳回 CSS 值的數字表示法。例如
num(11px)
產生11
;num(110ms)
產生110
;- 等等。
例如,以下運算式會計算與元素寬度成比例的延遲時間 (以秒為單位)
{ "delay": "calc(1s * num(width()) / 100)" }
覆寫子目標的效果
使用子目標覆寫在最上層動畫中定義的時間屬性或變數。透過 subtargets: []
定義子目標 (在與有效 selector
相同的空間中)。依索引或 CSS 選取器指定子目標。
{ "selector": ".target", "delay": 100, "--y": "100px", "subtargets": [ { "index": 0, "delay": 200 }, { "selector": ":nth-child(2n+1)", "--y": "200px" } ] }
在以上範例中
-
最上層動畫會將
".target"
比對到的目標預設為延遲時間100
和"--y"
為100px
。 -
"subtargets": []
包含第一個目標"index": 0
。此定義會將預設延遲時間100
覆寫為200
。 -
"subtargets": []
包含"selector": ":nth-child(2n+1)"
。此定義會將--y
變數的預設值100px
覆寫為200px
。
多個子目標可以比對一個目標 selector
元素。
SVG 動畫
SVG 很棒,我們建議您將其用於動畫!
amp-animation
元件支援具有允許清單 CSS 關鍵影格屬性的 SVG 動畫,但有以下細微差異
-
IE/Edge SVG 元素不支援 CSS
transform
屬性。雖然transform
動畫本身是 Polyfill,但樣式表中定義的初始狀態未套用。如果初始變形狀態在 IE/Edge 上很重要,建議透過 SVGtransform
屬性複製它。 -
無法為 IE/Edge Polyfill
transform-origin
。為了相容性,僅使用預設transform-origin
。 -
使用 CSS
transform-box
以避免transform-origin
解譯問題。請參閱 Chrome、Safari 和 Firefox 的問題。
相容性與回溯
使用媒體查詢、支援條件和切換陳述式以獲得平台相容性和回溯選項。
媒體查詢
使用 media
屬性指定媒體查詢。此屬性可以包含 Window.matchMedia API 允許的任何運算式,並對應於 @media
CSS 規則。
指定後,動畫元件只會在環境支援指定的 CSS 功能時執行。
Supports (支援) 條件
使用 supports
屬性指定支援條件。supports
屬性包含 CSS.supports
API 允許的任何運算式,並對應於 @supports
CSS 規則。
指定後,動畫元件只會在環境支援指定的 CSS 功能時執行。
動畫 switch
(切換) 陳述式
在某些情況下,您可能需要將條件式動畫與選填預設值合併到單一動畫中。使用 switch
動畫陳述式來定義條件。
{ // Optional selector, vars, timing ... "switch": [ { "media": "(min-width: 320px)", "keyframes": {...}, }, { "supports": "offset-distance: 0", "keyframes": {...}, }, { // Optional default: no conditionals } ] }
amp-animation
元件會依定義的順序評估 switch
動畫定義。它會執行第一個符合條件的動畫,並忽略其餘動畫。
在以下範例中,如果支援 motion-path 動畫,則會執行 motion-path 動畫,並回溯到 transform (變形)
{ "selector": "#target1", "duration": "1s", "switch": [ { "supports": "offset-distance: 0", "keyframes": { "offsetDistance": [0, "300px"] } }, { "keyframes": { "transform": [0, "300px"] } } ] }
合併與分割動畫
在 amp-animation
中定義的動畫可以互相參考。此功能允許將多個 amp-animation
宣告合併為單一動畫。將動畫分割成不同的 amp-animation
元件可重複使用較小的動畫,同時啟用與巢狀相同的效果。
<amp-animation id="anim1" layout="nodisplay"> <script type="application/json"> { "animation": "anim2", "duration": 1000, "--scale": 2 } </script> </amp-animation> <amp-animation id="anim2" layout="nodisplay"> <script type="application/json"> { "selector": ".target-class", "keyframes": {"transform": "scale(var(--scale))"} } </script> </amp-animation>
以上範例動畫將 "anim2"
動畫合併為 "anim1"
的一部分。"anim2"
不需要 selector
目標。在這種情況下,包含的動畫會參考自己的目標。
另一種形式允許包含的動畫提供目標或多個目標。在這種情況下,包含的動畫會針對每個比對到的目標執行。
<amp-animation id="anim1" layout="nodisplay"> <script type="application/json"> { "selector": ".target-class", "animation": "anim2", "duration": 1000, "--scale": 2 } </script> </amp-animation> <amp-animation id="anim2" layout="nodisplay"> <script type="application/json"> { "keyframes": {"transform": "scale(var(--scale))"} } </script> </amp-animation>
在以上範例中,"anim2"
會針對每個比對到的 ".target-class"
執行。在呼叫端動畫中指定的變數和時間屬性會傳遞至合併的動畫。
透過 on action (動作) 觸發
例如
<amp-animation id="anim1" layout="nodisplay"> ... </amp-animation> <button on="tap:anim1.start">Animate</button>
動畫的無障礙考量
如果您使用動畫來傳達意義或內容,請確保也以其他形式為可能無法看到這些動畫的使用者傳達此資訊。在最基本層面,請確保您的文字內容傳達與動畫相同的資訊。例如,如果您使用 <amp-animation>
來說明程序中的步驟順序,請確保也有文字 (在同一個頁面或連結頁面中) 以文字描述相同的步驟順序。
動畫通常無法由使用者暫停/停止。根據動畫的類型、大小以及是否循環/重複,這可能是輕微的分心,或對某些使用者群體造成重大問題 - 特別是當動畫包含快速閃爍的色彩變化時。一般而言,我們建議避免使用大型、無限重複的動畫,除非您確定它們不會對使用者產生負面影響。考慮提供控制項以允許使用者暫停動畫。考慮利用 prefers-reduced-motion
媒體查詢,並且僅在使用者未指示偏好減少動態/動畫時,才讓動畫生效。
<amp-animation ... media="not (prefers-reduced-motion: reduce)"> <!-- this animation will only play if the user has *not* expressed a preference for reduced motion --> ... </amp-animation>
您可以更進一步,並提供個別、更細微的回溯動畫,以便在 prefers-reduced-motion: reduce
評估為 true 時生效,或分割出無論媒體功能為何都應發生的較小動畫。
<amp-animation ... media="(prefers-reduced-motion: reduce)"> <!-- fallback subtle animation effects that only play if the user has expressed a preference for reduced motion --> ... </amp-animation> <amp-animation ...> <!-- general/common animation effects that will take effect regardless of any user preference for reduced motion --> ... </amp-animation>
如需更多詳細資訊,請參閱 MDN - prefers-reduced-motion
和這篇關於 web.dev - prefers-reduced-motion: Sometimes less movement is more (有時少一點動態效果更好) 的介紹文章。
對於並非純裝飾性/視覺效果,而是實際傳達資訊的動畫,請確保任何重要的文字和圖形/非文字元素都有足夠的色彩對比。如需簡介 (主要圍繞文字對比) 請參閱 web.dev 色彩與對比無障礙功能,如需更多關於非文字元素的詳細資訊,請參閱 Knowbility: Exploring WCAG 2.1 — 1.4.11 Non‑text Contrast (探索 WCAG 2.1 — 1.4.11 非文字對比)。
屬性
trigger (觸發條件)
決定何時應觸發動畫。必須設定為 visibility
,以便在故事頁面變為可見和啟用狀態時啟動動畫。
layout (版面配置)
應始終為 nodisplay
。
id
(選填)
動畫元件的 id
。用於參考動畫並串連一系列動畫。
動作
start (開始)
如果動畫尚未執行,則啟動動畫。時間屬性和變數。可以指定為動作引數。例如 anim1.start(delay=-100, --scale=2)
。
restart (重新開始)
啟動動畫或重新啟動目前正在執行的動畫。時間屬性和變數。可以指定為動作引數。例如 anim1.start(delay=-100, --scale=2)
。
pause (暫停)
暫停目前正在執行的動畫。
resume (繼續)
繼續目前正在執行的動畫。
togglePause (切換暫停)
切換暫停/繼續動作。
seekTo (搜尋至)
暫停動畫並搜尋至 time
引數 (以毫秒為單位) 或 percent
引數 (以時間軸中的百分點表示) 指定的時間點。
reverse (反向)
反轉動畫。
finish (完成)
完成動畫。
cancel (取消)
取消動畫。
amp-story 用法
如果您想要搭配 <amp-story>
使用 <amp-animation>
,請注意您應改用 <amp-story-animation>
。如需如何在 Advanced animations (進階動畫) 文件章節中使用它的詳細資訊。
驗證
請參閱 AMP 驗證器規格中的 amp-animation
規則。
您已閱讀此文件十幾次,但它實際上並未涵蓋您的所有問題?也許其他人也有相同的感受:在 Stack Overflow 上與他們聯繫。
前往 Stack Overflow 發現錯誤或缺少功能?AMP 專案非常鼓勵您的參與和貢獻!我們希望您能成為我們開放原始碼社群的持續參與者,但我們也歡迎針對您特別熱衷的問題提供一次性貢獻。
前往 GitHub