滚动绑定效果的基础知识
简介
amp-position-observer 与 amp-animation 结合使用是一个强大的构建块,可以处理各种用例,例如滚动绑定动画、视差效果以及当元素进入和退出视口时的过渡效果。
在本教程中,我们将详细介绍其中的一些用例。
设置
amp-position-observer 是一个功能组件,可监视用户滚动时元素在视口中的位置,并调度 enter
、exit
和 scroll:<Position In Viewport As a Percentage>
事件。
这些事件反过来可以用于 play
、pause
或 seek
由 amp-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-observer
和 amp-animation
背后的核心概念:当元素通过滚动在视口中移动时,能够通过关键帧动画时间轴前进。
我们的指尖陀螺场景是一个带有 image
的 div
。我们添加一个 amp-position-observer
元素作为场景的子元素,以监视其在视口中的进度。让我们看一下细节
on:scroll
:当用户滚动时场景的位置发生更改时,位置观察器会触发此事件。该事件提供一个百分比值(0 到 1 之间的十进制数),表示场景在其通过视口的进度开始和结束之间的距离。spinAnimation.seekTo(percent=event.percent)
:我们将在下一步定义一个amp-animation
来进行旋转,这里我们通过在scroll
事件发生时在动画上触发seekTo
操作来耦合amp-position-observer
和amp-animation
。这就是我们指定希望在场景通过滚动在视口中移动时通过动画时间轴前进的方式。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-observer
和 amp-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-animation
和 amp-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 上编辑示例-
由 @aghassemi 撰写