AMP

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

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 中指定的关键帧时,amp-animation 的 polyfills 在使用 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 允许的属性以优化性能。以下是允许的属性列表

不需要也不允许使用供应商前缀的 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 值。例如,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 传播到嵌套动画中,但它被覆盖。最终的 translate 值是 150px

  • --y 未在 <amp-animation> 组件中的任何位置指定。如果查询在 <amp style-custom> 标记中没有将其定义为 CSS,则它默认为 0px

Polyfills 应用于支持平台上的 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 匹配的第一个目标的 index0,第二个目标的 index1,依此类推。

除了其他用途外,此属性还可以与 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)"
}

覆盖子目标上的效果

使用子目标覆盖在顶级动画中定义的时间属性或变量。在需要的地方,在与有效的 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 组件支持使用允许的 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:有时少即是多 的介绍性文章。

对于不是纯粹装饰性/视觉效果而是实际传达信息的动画,请确保任何重要的文本和图形/非文本元素具有足够的颜色对比度。有关介绍(主要围绕文本对比度),请参阅 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