AMP
  • 网站

滚动绑定效果的基础知识

简介

amp-position-observeramp-animation 结合使用,是一个强大的构建块,可以处理各种用例,例如滚动绑定动画视差效果过渡,因为元素进入和退出视口。

在本教程中,我们将详细介绍其中一些用例。

设置

amp-position-observer 是一个功能组件,它会监控元素在用户滚动时在视口中的位置,并分派 enterexitscroll:<视口中位置的百分比> 事件。

这些事件反过来可以用于 playpauseseekamp-animation 定义的动画时间线,以创建滚动绑定和基于可见性的效果。

<script async custom-element="amp-position-observer" src="https://cdn.ampproject.org/v0/amp-position-observer-0.1.js"></script>

amp-animation 是一个 UI 组件,它依赖于 Web Animations API 来定义和运行 AMP 文档中的关键帧动画。

<script async custom-element="amp-animation" src="https://cdn.ampproject.org/v0/amp-animation-0.1.js"></script>

样式

这些示例使用的 CSS 包含在此处以供参考。

这些规则只是使示例工作所必需的,但不是此处涵盖的概念的基础。

<style amp-custom>

  /*
   * Fidget Spinner styles
   */
  .fidget-spinner-scene {
    margin: 10px 20%;
  }

  /*
   * Card transition styles
   */
  .card {
    margin: 10%;
    position: relative;
  }
  .card-title {
    padding: 5%;
    padding-right: 40%;
    font-size: 50%;
    font-weight: bold;
    color: #FAFAFA;
    transform: translateX(-100%);
  }

  /*
   * Parallax window styles
   */
  .parallax-image-window {
    overflow: hidden;
  }
  .parallax-image-window amp-img {
    margin-bottom: -30%;
  }

  /*
   * Carousel transition styles
   */
  .carousel-component {
    margin-right: -60%;
    margin-left: 60%;
  }
  .carousel-parent {
    overflow: hidden;
  }
</style>

滚动绑定动画

让我们创建一个随着用户滚动页面而旋转的指尖陀螺。

此示例展示了结合 amp-position-observeramp-animation 背后的核心概念:当元素通过滚动在视口中移动时,能够推进关键帧动画时间线。

我们的指尖陀螺场景是一个带有 imagediv。我们添加一个 amp-position-observer 元素作为场景的子元素,以监控其在视口中的移动进度。让我们看一下详细信息

  • on:scroll:当用户滚动时,场景的位置发生变化时,位置观察器会触发此事件。该事件提供一个百分比值(介于 0 和 1 之间的十进制数),表示场景在视口中的移动进度的开始和结束之间的距离。
  • spinAnimation.seekTo(percent=event.percent):我们将定义一个将在下一步中进行旋转的 amp-animation,在这里,我们将 amp-position-observeramp-animation 耦合在一起,通过在 scroll 事件发生时触发动画的 seekTo 操作。这就是我们指定,我们希望当场景通过滚动在视口中移动时,通过动画时间线进行推进。
  • intersection-ratios:定义在 amp-position-observer 触发任何事件之前,场景应在视口中可见多少。在这里,我们希望仅在指尖陀螺完全可见时才发生旋转,因此我们将其设置为 1
<div class="fidget-spinner-scene">

  <amp-position-observer on="scroll:spinAnimation.seekTo(percent=event.percent)" intersection-ratios="1" layout="nodisplay">
  </amp-position-observer>

  <amp-img id="fidgetSpinnerImage" width="1024" height="1114" layout="responsive" src="/static/samples/img/fidget.png" alt="Picture of a fidget spinner"></amp-img>
</div>

现在我们需要定义动画本身

在这种情况下非常简单,我们希望 fidgetSpinnerImage 旋转 360 度,因此我们只需定义一个 "transform": "rotate(360deg)" 作为最后一个(也是唯一的)关键帧。让我们看一下详细信息

  • id="spinAnimation":我们需要给动画一个 Id,以便我们可以从位置观察器引用它。
  • "duration": "1":在这种情况下,duration 的值是无关紧要的,因为我们通过滚动推进时间线,因此我们只需将其设置为 1
  • "direction": "reverse":这是由于 Web Animations 的 iOS 错误所必需的。
  • "animations":在这里,我们可以定义一个或多个基于关键帧的动画。在我们的例子中,我们只需要一个。
  • "selector""#fidgetSpinnerImage" 是用于定位动画的指尖陀螺的选择器。
  • "keyframes": 我们定义一个 "transform": "rotate(360deg)" 作为最后一个(也是唯一的)关键帧。请注意,如果未提供,amp-animation 会自动填充第一个关键帧。

amp-animation 还有许多其他功能,请参阅 API 参考以了解有关 amp-animations 的更多信息。

<amp-animation id="spinAnimation" layout="nodisplay">
  <script type="application/json">
    {
      "duration": "1",
      "fill": "both",
      "direction": "reverse",
      "animations": [
        {
          "selector": "#fidgetSpinnerImage",
          "keyframes": [
            { "transform": "rotate(360deg)" }
          ]
        }
      ]
    }
  </script>
</amp-animation>

淡入淡出和滑动过渡

现在我们已经了解了 amp-position-observeramp-animation 背后的基本核心概念,让我们深入探讨它们可以组合起来创建有趣过渡的更多创造性方法。

在此示例中,我们将时间绑定和滚动绑定过渡组合在一起,以创建一种效果,其中卡片的透明度与卡片在视口中的可见程度(滚动绑定)相关联,并且当卡片进入和退出视口时,卡片的标题会淡入/淡出(时间绑定)。

我们的卡片场景只是由图像和叠加的标题组成。在这里,我们定义两个具有不同 intersection-ratios 值的位置观察器

  • 第一个将控制用户滚动时图像的透明度。
  • 第二个将在场景大部分可见 (80%) 时为标题运行时间绑定的滑动动画,并在场景退出视口一点 (20%) 时再次“反向”运行。
有机新鲜的西红柿和意大利面!
<div class="card ampstart-card">

  <amp-position-observer on="scroll:fadeTransition.seekTo(percent=event.percent)" intersection-ratios="0" layout="nodisplay">
  </amp-position-observer>

  <amp-position-observer on="enter:slideTransition.start; exit:slideTransition.start,slideTransition.reverse" intersection-ratios="0.8" layout="nodisplay">
  </amp-position-observer>

  <amp-fit-text layout="fill">
    <div class="card-title">
      Organic, fresh tomatoes and pasta!
    </div>
  </amp-fit-text>

  <amp-img id="cardImage" width="1280" height="898" layout="responsive" src="/static/samples/img/food.jpg" alt="Picture of food table."></amp-img>
</div>

让我们定义滚动绑定淡入/淡出过渡的关键帧。

我们定位 #cardImage 并以一种方式定义关键帧,即图像在时间线的前 40% 内获得完全不透明度,并在时间线的最后 40% 中开始淡出。

请注意,由于控制此动画的位置观察器的 intersection-ratios 设置为 0,因此当用户滚动 ViewportHeight + 2 * SceneHeight 像素量时,我们将遍历整个时间线。

<amp-animation id="fadeTransition" layout="nodisplay">
  <script type="application/json">
    {
      "duration": "1",
      "fill": "both",
      "direction": "reverse",
      "animations": [
        {
          "selector": "#cardImage",
          "keyframes": [
            { "opacity": "0.3", "offset": 0 },
            { "opacity": "1", "offset": 0.4 },
            { "opacity": "1", "offset": 0.6 },
            { "opacity": "0.3", "offset": 1 }
          ]
        }
      ]
    }
  </script>
</amp-animation>

对于标题的滑动淡入/淡出效果,我们只需定义一个 500 毫秒的动画,该动画将使标题沿 X 轴移动。

当场景大部分可见/不可见时,此动画将通过第二个位置观察器简单地触发(以正常或相反方向)。

<amp-animation id="slideTransition" layout="nodisplay">
  <script type="application/json">
    {
        "duration": "500ms",
        "fill": "both",
        "easing": "ease-out",
        "iterations": "1",
        "animations": [
          {
            "selector": ".card-title",
            "keyframes": [
              { "transform": "translateX(-100%)" },
              { "transform": "translateX(0)" }
            ]
          }
        ]
      }
  </script>
</amp-animation>

视差图像窗口

视差是另一种可以通过组合 amp-animationamp-position-observer 实现的效果。

视差通常涉及在用户滚动时沿 Y 轴平移元素。

在这里,我们定义一个场景,该场景的高度小于其中的图像的高度,当用户滚动时,我们移动图像,从而在图像中创建一个视差窗口。

<div class="parallax-image-window">

  <amp-position-observer on="scroll:parallaxTransition.seekTo(percent=event.percent)" intersection-ratios="0" layout="nodisplay">
  </amp-position-observer>

  <amp-img id="parallaxImage" width="1280" height="873" layout="responsive" src="/static/samples/img/elephant.jpg" alt="Picture of an elephant"></amp-img>
</div>

动画本身只是通过 "transform": "translateY(-30%)" 向上移动图像

<amp-animation id="parallaxTransition" layout="nodisplay">
  <script type="application/json">
    {
      "duration": "1",
      "fill": "both",
      "direction": "reverse",
      "animations": [
        {
          "selector": "#parallaxImage",
          "keyframes": [
            { "transform": "translateY(-30%)" }
          ]
        }
      ]
    }
  </script>
</amp-animation>

我们还可以将这些效果与其他 AMP 组件(例如 amp-carousel)结合使用。

在此示例中,我们有一个轮播,其中第一个项目被推到右侧,当轮播变得可见时,它会捕捉回原位,从而提供视觉上的“提示”,表明轮播是水平可滚动的。

<div class="carousel-parent">
  <amp-carousel class="carousel-component" height="300" layout="fixed-height" type="carousel">

    <amp-position-observer on="enter:carouselTransition.start" intersection-ratios="0.8" layout="nodisplay">
    </amp-position-observer>

    <amp-img src="https://unsplash.it/800/600?image=1003" width="400" height="300" alt="a sample image"></amp-img>
    <amp-img src="https://unsplash.it/800/600?image=1043" width="400" height="300" alt="another sample image"></amp-img>
    <amp-img src="https://unsplash.it/800/600?image=1032" width="400" height="300" alt="and another sample image"></amp-img>
  </amp-carousel>
</div>

在这里,我们定义了带有 200 毫秒延迟的时间绑定动画,该动画将在 500 毫秒内将轮播滑动到左侧。

此动画将仅由位置观察器触发一次,如上所述。

<amp-animation id="carouselTransition" layout="nodisplay">
  <script type="application/json">
    {
      "duration": "500ms",
      "fill": "both",
      "easing": "ease-in",
      "delay": "200ms",
      "animations": [
        {
          "selector": ".carousel-component",
          "keyframes": [
            { "transform": "translateX(-60%)" }
          ]
        }
      ]
    }
  </script>
</amp-animation>
需要进一步解释?

如果此页面上的解释没有涵盖您的所有问题,请随时与其他 AMP 用户联系,讨论您的确切用例。

前往 Stack Overflow
未解释的功能?

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

在 GitHub 上编辑示例