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 (持續時間) | 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
會傳播到巢狀動畫中,但它會被覆寫。結束轉譯值為150px
。 -
--y
未在<amp-animation>
元件中的任何位置指定。如果查詢未在<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 很棒,我們建議將它們用於動畫!
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 的問題。
相容性和回溯
將媒體查詢、支援條件和 switch 陳述式用於平台相容性和回溯選項。
媒體查詢
使用 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 動畫,則會執行該動畫,否則會回溯到 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:有時少一點動作更好 的入門文章。
對於並非純粹裝飾性/視覺效果,而是實際傳達資訊的動畫,請確保任何重要的文字和圖形/非文字元素都具有足夠的色彩對比度。如需簡介 (主要圍繞文字對比度) 請參閱 web.dev 色彩和對比度無障礙功能,如需更多有關非文字元素的詳細資訊,請參閱 Knowbility:探索 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-animation>
與 <amp-story>
搭配使用,請注意您應該改用 <amp-story-animation>
。如需有關如何使用它的更多資訊,請參閱文件中的 進階動畫 章節。
驗證
請參閱 AMP 驗證器規格中的 amp-animation
規則。
您已閱讀此文件十幾次,但它實際上並未涵蓋您的所有問題?也許其他人也有同樣的感覺:在 Stack Overflow 上與他們聯繫。
前往 Stack Overflow 發現錯誤或缺少功能?AMP 專案強烈鼓勵您的參與和貢獻!我們希望您能成為我們開放原始碼社群的持續參與者,但我們也歡迎針對您特別熱衷的問題提供一次性貢獻。
前往 GitHub