複雜動畫簡介
對於無法透過新增和移除類別驅動的動畫,AMP 提供了數個專為動畫設計的元件。這些元件將 AMP 的原則應用於動畫:它們快速、有效率且以使用者優先。AMP 限制了關鍵影格中允許的 CSS 屬性,但也提供了精細控制、無縫動畫以及跨瀏覽器相容性等優點,無需額外工作。
如果您需要嚴密控制播放,以及精確控制多個元素同時製作動畫的時間,請使用 amp-animation。
建立基本的 AMP 動畫
amp-animation
元件讓您可以在 AMP 中使用 Web Animation API。
基本的 amp-animation
是一個 JSON 物件,由以下主要部分組成
<amp-animation layout="nodisplay" id="exampleAnimation">
<script type="application/json">
{
"selector": "#elementID", //select the element to animate
"duration": "1s", //timing property
"iterations": 2, //timing property
"fill": "both", //timing property
"keyframes": {"opacity": 0, "transform": "scale(2)"} //keyframes
}
</script>
</amp-animation>
<!-- trigger -->
<button on="tap:exampleAnimation.start">
選取器
與 CSS 非常相似,amp-animation
元件透過在 "selector"
欄位中宣告元素的標籤名稱、類別或 ID,將動畫屬性連結到元素。此元件會為每個宣告的標籤類型或類別名稱元素製作動畫。使用 ID 可確保您只為單一元素製作動畫。
時間屬性
時間屬性控制動畫的持續時間、播放次數以及關鍵影格的執行方向。
雖然並非必要,但如果缺少與時間和顯示相關的屬性 (例如 duration
(持續時間) 和 fill
(填滿)),動畫可能無法執行。
關鍵影格
雖然 CSS 允許您透過轉場效果從一個狀態變形到另一個狀態,但您必須將動畫屬性宣告為關鍵影格,才能實作 amp-animation
。可用的屬性是 GPU 加速的屬性,這些屬性不會導致重新配置版面,而且可以在合成器執行緒上製作動畫。這樣可防止動畫干擾 AMP 和瀏覽器的轉譯程序。
amp-animation
中定義。觸發器
觸發器會啟動動畫序列。amp-animation
擴充功能會在 <body>
在網頁上變成可見時,或透過將其連結到 AMP 動作或事件時啟動
當動畫應在網頁載入後立即執行時 (因為它顯示在「首頁上方」或網頁的第一個可視區域內),在 <body>
可見時觸發會很有用。動畫會透過可見性觸發,方法是將 trigger="visibility"
新增為元件的屬性。
<amp-animation layout="nodisplay"
trigger="visibility">
...
</amp-animation>
動畫會透過將 amp-animation
元件指派 id
,並將該 id
連結到所需的事件觸發器 (例如輕觸按鈕),來連結到動作或事件。
<amp-animation layout="nodisplay" id="exampleAnimation">
...
</amp-animation>
<button on="tap:exampleAnimation.start">
建置複雜動畫
在 amp-animation
中建置動畫可進行精細的控制,而不僅僅是啟動和停止動畫:它還可以暫停、倒轉和直接指向特定點。您甚至可以將多個動畫串鏈在一起,並依序為元素製作動畫。
子目標
相同標籤或類別的元素可以有指定的時間屬性,並覆寫在頂層動畫中定義的變數值。
<body>
<h1>Hello World!</h1>
<h1>Hello World!</h1>
<h1 id="helloMe">Hello World!</h1>
<h1>Hello World!</h1>
<amp-animation layout="nodisplay" id="animateThis">
<script type="application/json">
{
"selector": "h1",
"duration": "3s",
"fill": "both",
"keyframes": [
{"transform": "translateX(0px)"},
{"transform": "translateX(50%)"}
],
"subtargets": [
{
"index": 1,
"duration": "1s"
},
{
"selector": "#helloMe",
"direction": "reverse",
"duration": "5s"
}
]
}
</script>
</amp-animation>
<button on="tap:animateThis.start">start</button>
</body>
串鏈動畫
多個動畫可以連結在一起形成大型序列。您可以透過在 amp-animation
元件內的 animations
陣列中編寫動畫,來建立定時效果,例如影片上的疊加層。
<amp-animation id="overlaysAnim" layout="nodisplay">
<script type="application/json">
{
"duration": "3s",
"fill": "both",
"animations": [{
"selector": ".one",
"keyframes": [{
"opacity": "1",
"offset": 0
},
{
"opacity": "1",
"offset": 0.04
},
{
"opacity": "0",
"offset": 0.0401
},
{
"opacity": "0",
"offset": 1
}
]
},
]
}
</script>
</amp-animation>
此設定會依序播放每個動畫 3 秒。
對於較大的動畫,animations
陣列內的動畫能夠參照其他 amp-animation
元件。
<amp-animation id="addEnergy" layout="nodisplay">
<script type="application/json">
{
"duration": "0.3s",
"fill": "both",
"direction": "alternate",
"animations": [
{
"selector": "#energy",
"keyframes": [
{"transform": "scaleX(calc(num(width('#energy'))/10))"},
{"transform": "scaleX(calc(num(width('#energy'))/10 + 3))"}
]
},
{
"animation": "atomExcite"
}
]
}
</script>
</amp-animation>
<amp-animation id="atomExcite" layout="nodisplay" trigger="visibility">
<script type="application/json">
{
"duration": "0.3s",
"iterations": "2",
"fill": "both",
"direction": "alternate",
"animations": [
{
"selector": ".atom",
"keyframes": {
"transform": "translate(20vw)"
}
}
]
}
</script>
</amp-animation>
為未知數量的元素製作動畫
透過使用 [`var(/content/amp-dev/documentation/components/reference/amp-animation.md#css-extensions), 您可以編寫複雜且定時的動畫,這些動畫可與任何數量的元素搭配使用。這樣可以輕鬆流暢地為動態和使用者產生的資料製作動畫。
<head>
<script
async
custom-element="amp-animation"
src="https://cdn.ampproject.org/v0/amp-animation-0.1.js"
></script>
<style amp-custom>
.parent {
perspective: 1000px;
transform-style: preserve-3d;
position: relative;
margin: 10px;
width: 239px;
height: 335px;
}
.card {
transform-origin: left;
height: 50%;
width: 50%;
}
</style>
</head>
<body>
<amp-animation layout="nodisplay" id="cardAdmin">
<script type="application/json">
{
"selector": ".card",
"--duration": "2s",
"duration": "var(--duration)",
"delay": "calc((length() - index() - 1) * var(--duration))",
"easing": "ease-in",
"iterations": "1",
"fill": "both",
"keyframes": [
{"transform": "translate3d(0px, 0px, 0px)"},
{"transform": "translate3d(50%, 0px, 100px)"},
{"transform": "translate3d(110%, 0px, 0px) rotateY(-20deg)"},
{"transform": "translate3d(50%, 0px, -100px)"},
{"transform": "translate3d(0px, 0px, -1px)"}
]
}
</script>
</amp-animation>
<div class="parent" on="tap:cardAdmin.start" tabindex="none" role="animation">
<amp-img
class="card"
src="https://upload.wikimedia.org/wikipedia/commons/7/70/3C.svg"
layout="fill"
></amp-img>
<amp-img
class="card"
src="https://upload.wikimedia.org/wikipedia/commons/3/3a/3H.svg"
layout="fill"
></amp-img>
<amp-img
class="card"
src="https://upload.wikimedia.org/wikipedia/commons/e/e1/KC.svg"
layout="fill"
></amp-img>
</div>
</body>
此範例的運作方式如下
- 宣告變數
--duration
,並將其值設為兩秒。 - 將
duration
(持續時間) 設定為變數--duration
的值。 - 計算套用至每個類別為
.card
的元素的延遲。1. [length(/content/amp-dev/documentation/components/reference/amp-animation.md#css-length()-extension) 會計算選取了多少
.card元素 1. 然後長度會減去每個
.card的 [index(/content/amp-dev/documentation/components/reference/amp-animation.md#css-index()-extension) 1. 將結果值乘以變數
--duration` 1. 最後總計以秒為單位套用至該元素的延遲 - 動畫會個別套用至每個元素,以便卡片依序洗牌,而不是同時洗牌。
在 AMP Playground 中開啟動畫,並新增更多 amp-img
元素來測試此行為。
在任何地方都美觀呈現
動畫可以包含 conditions
(條件)。
<head>
<style amp-custom>
.drop {
width: 20px;
height: 20px;
background: blue;
margin-top: 1em;
border-radius: 50%;
}
.right {
position: absolute;
right: 0;
background: red;
}
</style>
<script
async
custom-element="amp-animation"
src="https://cdn.ampproject.org/v0/amp-animation-0.1.js"
></script>
</head>
<body>
<amp-animation id="mediaAnimation" layout="nodisplay">
<script type="application/json">
{
"duration": "1s",
"iterations": "4",
"fill": "both",
"direction": "alternate",
"animations": [
{
"media": "(min-width: 300px)",
"selector": ".drop",
"keyframes": {
"transform": "translate(100vw)"
}
},
{
"media": "(max-width: 300px)",
"selector": ".drop",
"keyframes": {
"transform": "translate(50vw)"
}
},
{
"media": "(min-width: 300px)",
"selector": ".right",
"keyframes": {
"transform": "translate(-100vw)"
}
},
{
"media": "(max-width: 300px)",
"selector": ".right",
"keyframes": {
"transform": "translate(-50vw)"
}
}
]
}
</script>
</amp-animation>
<div class="rain">
<div class="drop"></div>
<div class="drop right"></div>
<div class="drop"></div>
<div class="drop right"></div>
<div class="drop"></div>
<div class="drop right"></div>
<div class="drop"></div>
<div class="drop right"></div>
</div>
<button on="tap:mediaAnimation.start">Start</button>
</body>
-
作者: @CrystalOnScript