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)"}
  ]
}

数组形式还可以显式包含 "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 中指定的关键帧时,amp-animation 的 polyfill 将在使用 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 时间 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>

您可以声明 CSS 变量以通过 var() 表达式用于定时和关键帧值。

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>

在上面的示例中

  • 嵌套动画将 var --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,第二个为 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 动画定义。它会执行第一个匹配条件的动画,并忽略其余的动画。

在下面的示例中,如果支持运动路径动画,则会运行该动画,否则会回退到变换

{
  "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 action 触发

例如

<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-story> 中使用 <amp-animation>,请注意您应该使用 <amp-story-animation> 来代替。有关如何使用它的更多信息,请查看文档的 高级动画 部分。

验证

请查看 AMP 验证器规范中的 amp-animation 规则

需要更多帮助?

您已经阅读本文档很多遍了,但它仍然没有涵盖您所有的问题?也许其他人也有同样的感受:请在 Stack Overflow 上联系他们。

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

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

前往 GitHub