在浏览 iPhone15 概览页时,它的按钮动画引起了我的兴趣:
本篇文章将借助 js 动画库 GSAP (GreenSock Animation Platform) 对如上图所示的按钮出现和隐藏动画进行实现。
GSAP 初体验
首先来实现黑色圆放大出现的动画以了解 gsap 的基本用法,它的 html + css 代码很简单:
<div id="btn"></div>
#btn {
width: 56px;
height: 56px;
border-radius: 28px;
background-color: rgb(66 66 69);
}
效果如下:
现在开始添加动画,直接使用 cdn 的形式引入 gsap,如此在 window 对象上就会添加 gsap 对象。
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
通过 gsap.timeline() 创建时间线实例 tl:
const tl = gsap.timeline()
有了动画时间线,就可以方便我们添加一系列的补间动画,并让它们按顺序依次播放。先通过 tl.from() 让圆从我们传入的状态变换到前面用 css 定义的应该呈现的状态:
tl.from('#btn', {
scale: 0,
transformOrigin: 'bottom',
duration: 1,
ease: 'power1.in'
})
tl.from() 的第 1 个参数为添加动画的目标元素,我们传入的'#btn',gsap 会传给 document.querySelectorAll();第 2 个参数是一个对象,里面可以放 css 属性或是其它一些特殊属性比如 onComplete: () => {} 用于定义该补间动画完成时要执行的代码。下面介绍用到的几个属性:
scale: 0的作用相当于给圆的初始样式添加上transform: scale(0, 0),除了缩放,其它关于transform的缩写在 gsap 官网中有如下表格进行了说明:
transformOrigin 的值也可以直接使用 'bottom' 这样的字符串;
duration: 1代表动画的持续时间为 1s,默认值为0.5;ease用于描述动画的速率曲线,其不同值所代表的意义在官网中也有个演示可以直观地感受:
power1.in 表示动画将先慢后快。
通过简单的配置,一个黑色实心圆从底部由小到大出现的动画就实现了:
在创建时间线实例时,也可以传入一些配置:
const tl = gsap.timeline({
repeat: -1, // 一直重复
yoyo: true, // 下一次循环,动画会以相反的方向运行
repeatDelay: 1 // 重复动画前等待 1 s
})
那么动画效果如下:
完成按钮动画
在了解完第一个动画效果的实现原理后,之后无非是通过链式调用不同的方法(除了 from 和 to,时间线实例还有很多方法,可参见官方文档),给各个元素依次添加上动画效果而已,from 是设置从某个初始状态到当前状态(也就是没有添加动画时的状态)的动画,而 to 方法是设置从当前状态要到达的目标状态:
tl.from(['#btn', '#blue-circle'], {
scale: 0,
duration: 1,
ease: 'power1.in',
stagger: 0.5
})
.to('#blue-circle', {
scale: 0
})
.from('#icon', {
scale: 0
})
.to('#btn', {
width: 200
})
.to(
'#icon',
{
x: 50
},
'<'
)
.from(
'.text',
{
opacity: 0,
x: -12
}
)
下面做一些特别说明:
from,to,这些方法的第 1 个参数还可以是个数组,表明数组里的元素都将应用相同的动画配置,stagger: 0.5表示#blue-circle的动画会比#btn的晚开始 0.5s;- 第 21 行的
'<'表示#icon的 x 轴平移动画和上一个补间动画,即#btn的宽度变为 200px 一起开始; - 具体的 html 和 css 等完整代码我会通过码上掘金展示。
至此,按钮动画如下:
使用 ScrollTrigger 插件
iPhone15 概览页的效果是当页面滚动到指定的区域,按钮才会出现,页面离开指定区域则按钮消失。我们可以借助 gsap 提供的 ScrollTrigger 插件来实现这一效果,插件需要单独引入 cdn:
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/ScrollTrigger.min.js"></script>
使用前先注册插件:
gsap.registerPlugin(ScrollTrigger)
然后在创建时间线实例时,传入参数如下:
const tl = gsap.timeline({
scrollTrigger: {
trigger: '.box',
start: 'top 80%', // 开始位置
onLeaveBack: () => {
tl.reverse()
}
}
})
scrollTrigger.trigger用于指定触发时间线动画的元素;start: 'top 80%'表示当.box的顶部与浏览器滚动条从上往下算 80% 长度的区域相遇时,开始触发动画:
onLeaveBack即当滚动条往上回滚,移动超过了start指定的位置时(具体说就是滚动条 80% 的位置位于按钮的顶部的上方)触发的回调,我直接使用tl.reverse()让整个时间线动画反转,而没有像iPhone15 概览页效果那样再进行些动画的设计了。
最终效果