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)"} ] }
数组形式还可以包含“缓动”
{ "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 中指定关键帧时,
amp-animation
的填充将因使用calc()
和var()
而失败。使用 CSS 中的备用值来避免这种情况。 -
width()
、height()
、x()
、y()
、num()
、rand()
、index()
和length()
等 CSS 扩展不可用于@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 。 |
迭代 | 数字或 “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>
您可以通过 var()
表达式声明 CSS 变量以用于时序和关键帧值。
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)" }
覆盖子目标上的效果
使用子目标覆盖顶级动画中定义的时间属性或变量。在与有效 selector
相同的空间中,在需要的地方通过 subtargets: []
定义子目标。按索引或 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
组件支持 SVG 动画,其中列出了允许的 CSS 关键帧属性,并带有以下细微差别
-
IE/Edge SVG 元素 不支持 CSS
transform
属性。虽然transform
动画本身是填充的,但样式表中定义的初始状态不会应用。如果初始转换状态在 IE/Edge 中很重要,建议通过 SVGtransform
属性 复制它。 -
不可能为 IE/Edge 填充
transform-origin
。为了兼容性,仅使用默认的transform-origin
。 -
使用 CSS
transform-box
以避免transform-origin
解释问题。请参阅 Chrome、Safari 和 Firefox 的问题。
兼容性和后备
使用媒体查询、支持条件和 switch 语句以实现平台兼容性和后备选项。
媒体查询
使用 media
属性指定媒体查询。此属性可以包含 Window.matchMedia API 允许的任何表达式,并且对应于 @media
CSS 规则。
指定后,仅当环境支持指定的 CSS 功能时,动画组件才会执行。
支持条件
使用 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
动画定义。它执行第一个与条件匹配的动画,并忽略其余动画。
在下面的示例中,如果支持,动画将运行运动路径动画,并回退到转换
{ "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 非文本对比度以了解有关非文本元素的更多详细信息。
属性
触发器
确定何时应触发动画。这必须设置为visibility
,以便动画在故事页面变为可见且处于活动状态时开始。
布局
应始终为nodisplay
。
id
(可选)
动画组件的id
。用于引用动画和链接一系列动画。
操作
开始
如果动画尚未运行,则启动动画。时序属性和变量。可以指定为操作参数。例如:anim1.start(delay=-100, --scale=2)
。
重新开始
启动动画或重新启动当前正在运行的动画。时序属性和变量。可以指定为操作参数。例如:anim1.start(delay=-100, --scale=2)
。
暂停
暂停当前正在运行的动画。
恢复
恢复当前正在运行的动画。
切换暂停
切换暂停/恢复操作。
seekTo
暂停动画并根据以毫秒为单位的time
参数或以时间线中百分点为单位的percent
参数指定的时间点进行查找。
反转
反转动画。
完成
完成动画。
取消
取消动画。
amp-story 用法
如果您想将<amp-animation>
与<amp-story>
一起使用,请注意您应该使用<amp-story-animation>
。有关如何使用它的更多信息,请参阅文档的高级动画部分。
验证
请参阅 AMP 验证器规范中的amp-animation
规则。
您已经阅读了本文档十几次,但它并没有真正涵盖您所有的问题?也许其他人也有同感:在 Stack Overflow 上联系他们。
转到 Stack Overflow 发现错误或缺少功能?AMP 项目强烈鼓励您参与和贡献!我们希望您成为我们开源社区的持续参与者,但我们也欢迎您对您特别热衷的问题做出一次性贡献。
转到 GitHub