滚动绑定效果基础
简介
amp-position-observer 与 amp-animation 结合使用是一个强大的构建块,可以处理各种用例,例如滚动绑定动画、视差效果和当元素进入和退出视口时的过渡。
在本教程中,我们将详细介绍其中一些用例。
设置
amp-position-observer 是一个功能性组件,它会在用户滚动时监视元素在视口中的位置,并派发 enter
、exit
和 scroll:<视口中位置的百分比>
事件。
这些事件反过来可以用于 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