重要事項:這份文件不適用於您目前選取的格式:電子郵件!
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 結構中定義動畫。最上層區段會宣告目標元素、執行條件、時間屬性和 影格效果,藉此定義整體動畫。整體程序可以包含任意數量的動畫部分,這些部分定義在 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
屬性或 動作,觸發一個或多個動畫的開始。
您可以將透過動作控制的 amp-animation
放置在 DOM 中的任何位置。如果動畫包含 trigger="visibility"
,則會在父元素進入可視區域時觸發,並在離開可視區域時暫停。
定義效果
影格
您必須將效果宣告為影格,才能使用 amp-animations
套用動畫。
您可以使用與 MDN 的 影格格式中定義的相同方式,在 amp-animation 中指定影格。您也可以參考在 <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
的 Polyfill 會失敗。在 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 (持續時間) | 時間 | 0 | 動畫持續時間。數值 (以毫秒為單位) 或 CSS 時間值,例如 2s 。 |
delay (延遲) | 時間 | 0 | 動畫開始執行前的延遲時間。數值 (以毫秒為單位) 或 CSS 時間值,例如 2s 。 |
endDelay (結束延遲) | 時間 | 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
會傳播到巢狀動畫中,但會遭到覆寫。結束轉譯值為150px
。 -
<amp-animation>
元件中未指定--y
。如果查詢找不到在<amp style-custom>
標記中定義為 CSS 的值,則預設為0px
。
Polyfill 會同時套用至支援平台上的 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 很棒,我們建議您使用 SVG 製作動畫!
amp-animation
元件支援 SVG 動畫以及允許清單中的 CSS 影格屬性,但有以下細微差異
-
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 的問題。
相容性和回退機制
使用媒體查詢、支援條件和 switch 陳述式以獲得平台相容性和回退選項。
媒體查詢
使用 media
屬性指定媒體查詢。此屬性可以包含 Window.matchMedia API 允許的任何算式,並且對應於 @media
CSS 規則。
指定後,動畫元件只會在環境支援指定的 CSS 功能時執行。
Supports 條件
使用 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 動畫時執行,並回退到 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 動作觸發
例如
<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:有時少即是多 的入門文章。
對於非純裝飾性/視覺效果,而是實際傳達資訊的動畫,請確保任何重要的文字和圖形/非文字元素都具有足夠的色彩對比。如需簡介 (主要圍繞文字對比) 和 Knowbility:探索 WCAG 2.1 — 1.4.11 非文字對比,請參閱 web.dev 色彩和對比度無障礙功能,以取得更多詳細資訊 (主要圍繞文字對比)。
屬性
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-animation>
與 <amp-story>
搭配使用,請注意您應改用 <amp-story-animation>
。如需如何使用的詳細資訊,請參閱文件中的進階動畫章節。
驗證
請參閱 AMP 驗證器規格中的 amp-animation
規則。
您已閱讀這份文件十幾次,但它實際上並未涵蓋您的所有問題?也許其他人也有相同感受:在 Stack Overflow 上與他們交流。
前往 Stack Overflow 發現錯誤或缺少功能?AMP 專案強烈鼓勵您的參與和貢獻!我們希望您能成為我們開放原始碼社群的長期參與者,但我們也歡迎針對您特別感興趣的問題提供一次性貢獻。
前往 GitHub