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 应用动画。

你可以在 amp-animation 中指定关键帧,方式与 MDN 的 关键帧格式 中定义的方式相同。你也可以引用在 <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)"}
  ]
}

数组形式也可以显式包含“偏移”

{
  "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 @keyframesWeb 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 允许的属性,以优化性能。以下是允许的属性列表

既不需要也不允许使用带有供应商前缀的 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 传播到嵌套动画中,但它被覆盖了。最终的 translate 值是 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,第二个为 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 组件支持 SVG 动画,但只允许使用已列出的 CSS 关键帧属性,并具有以下细微差别:

  • 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 非文本对比度

属性

触发器

确定何时应触发动画。必须将其设置为 visibility,以便在故事页面变为可见和活动状态时启动动画。

布局

应始终为 nodisplay

id(可选)

动画组件的 id。用于引用动画并链接一系列动画。

操作

开始

如果动画尚未运行,则启动它。定时属性和变量。可以指定为操作参数。例如,anim1.start(delay=-100, --scale=2)

重新开始

启动动画或重新启动当前正在运行的动画。定时属性和变量。可以指定为操作参数。例如,anim1.start(delay=-100, --scale=2)

暂停

暂停当前正在运行的动画。

恢复

恢复当前正在运行的动画。

切换暂停

切换暂停/恢复操作。

跳转到

暂停动画,并跳转到由 time 参数(以毫秒为单位)或 percent 参数(作为时间线中的百分比点)指定的时间点。

反向

反转动画。

完成

完成动画。

取消

取消动画。

amp-story 用法

如果您想将 <amp-animation><amp-story> 一起使用,请注意您应该改用 <amp-story-animation>。有关如何使用它的更多信息,请参阅文档的 高级动画 部分。

验证

请参阅 AMP 验证器规范中的 amp-animation 规则

需要更多帮助?

您已经阅读本文档十几次了,但它并没有真正涵盖您的所有问题?也许其他人也有同样的感受:在 Stack Overflow 上联系他们。

前往 Stack Overflow
发现错误或缺少功能?

AMP 项目强烈鼓励您的参与和贡献!我们希望您能成为我们开源社区的长期参与者,但我们也欢迎您为自己特别感兴趣的问题做出一次性贡献。

前往 GitHub