AMP

重要提示:此文档不适用于您当前选择的格式电子邮件

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 @keyframesWeb Animations 规范中的 JSON 内联关键帧定义相匹配,但有以下细微差别

  • 您可能需要供应商前缀,例如 @-ms-keyframes {}-moz-transform 以获得广泛的平台支持。JSON 格式不需要也不允许使用供应商前缀,但在 CSS 中,它们可能是必要的。

  • 在不支持的平台上,当使用 CSS 中指定的关键帧使用 calc()var() 时,amp-animation 的 polyfill 将会失败。在 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 允许的属性以优化性能。以下是允许的属性列表

不需要也不允许使用供应商前缀的 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 值。例如,10001s1000m 都是 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() 对于变换特别有用。 lefttop 和类似的 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 上很重要,建议通过 SVG transform 属性复制它。

  • 不可能为 IE/Edge polyfill transform-origin。为了兼容性,请仅使用默认的 transform-origin

  • 使用 CSS transform-box 以避免 transform-origin 的解释问题。请参阅关于 ChromeSafariFirefox 的问题。

兼容性和回退

使用媒体查询、支持条件和 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 动画定义。它执行第一个匹配条件的动画,并忽略其余的动画。

在下面的示例中,如果支持,动画会运行 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