【前端入门系列】HTML5动画与动效(之二)
在本系列的第一篇文章中我们对transition动画有了基础的了解,本节我们将通过为图标元素创建动画效果,以此来着重学习另一种动画制作方法:animation动画。因此,本节的主题就是animation动画的理解与运用。
什么是animation动画?
和transition动画一样,animation动画也是CSS3动画的一种。这类动画可以理解为是一种关键帧动画,它可以预先为动画设置多个节点,在每个节点中含有不同的状态属性,通过使用animation动画我们可以得到更为复杂的动画效果。
复习一下:transition是为页面元素设置某个需要产生动画效果的属性,如宽度(width)、高度(height)、透明度(opacity),甚至3D旋转等,并使得这些属性的值在发生变化时产生相应的过渡效果。我们常常在制作类似按钮鼠标经过和移出效果时使用transition。通俗地说,transition是简化版的CSS3动画,而animation则是 强化版的CSS3动画。在日常开发中transition的使用频率更高一些,我们往往只有在遇到transition无法解决的问题时,才会转而使用animation。
DOM和CSS的准备
首先,准备一个span元素作为图标的载体(也可以使用其他元素,如div、a、button等)。代码如下:
<span class="close">Close</span>
在此我们使用设置了icon字体的伪元素来生成图标图案,代码如下:
.close{
font-size:0px; /*使span中的文字不显示*/
cursor:pointer; /*使鼠标指针显示为手型*/
display:block;
width:100px;
height:100px;
line-height:100px;
border-radius:50%; /*使背景形状显示为圆形*/
background:#FFF;
color:#8b8ab3;
text-align:center;
}
.close::before{
content:"\e609";
font-family: 'icon-font';
speak:none; /*使文本内容不能通过屏幕阅读器等辅助设备读取*/
font-size:48px;
display:block;
}
在以上代码中绘制了一个圆形按钮,其原理是通过设置span原本的字体大小为0来隐藏“Close”文字,并通过设置属性值为50%的圆角来实现圆形效果。此外,我们还添加了speak:none属性来为该元素增强可访问性,使得有阅读障碍的浏览者不会被插入的伪元素中的无意义字符所困扰。圆形图标效果如图所示。
初试animation动画
接下来,我们为鼠标指针的滑过状态设置一些动画效果。在此,我们希望当鼠标指针滑过时,图标在1秒内匀速旋转360度。我们在此先复习一下transition动画的用法,代码如下:
.close:hover::before{
-webkit-transform:rotate(360deg);
transform:rotate(360deg);
-webkit-transition:-webkit-transform 1s linear;
transition:transform 1s linear;
}
在以上代码中,我们使用了transform属性来实现图标的旋转,并且设置了transition动画,将变化的属性名称设置为transform。测试页面,现在我们将看到图标的旋转效果,如图所示。
注意:在设置旋转属性时,需要加上deg作为度数单位,即使是旋转0度也需要同样添加这一单位。此外,transform只是一种变换属性,其本身不能生成动画效果,它只能通过与transition或animation属性的配合才能产生动画效果。
当前的图标只会旋转一次,然后将停止下来。而如果我们希望图标能够一直不停旋转,则需要请出animation动画。使用animation动画的前提是先制作动画的各个关键帧,代码如下:
@-webkit-keyframes spin { /*兼容性写法*/
from {
-webkit-transform: rotate(0deg);
}
to {
-webkit-transform: rotate(360deg);
}
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
在以上代码中,我们使用了keyframes关键字来定义了一个名为spin的关键帧动画,在该动画中使用了from关键字来指定动画的起始状态,to关键字来指定动画的结束状态。在起始状态中设置transform属性的旋转度为0度,在结束状态中设置该旋转度为360度。此外,我们还添加了-webkit-前缀以确保动画在webkit浏览器中的兼容性。
在指定了spin关键帧动画后,我们就可以在图标中运用这一动画,代码如下:
.close:hover::before{
-webkit-animation: spin 1s linear;
animation: spin 1s linear;
}
在以上代码中,我们设置了鼠标滑过状态下伪元素的animation属性,该属性的第一个参数是动画名称,即spin,第2个参数是动画时长,在此设置为1秒,第3个属性为速度曲线,在此设置为匀速运动。测试页面,现在我们能够得到和之前transition动画相同的效果,如图所示。
给animation动画添加各种参数
如果我们希望图标一直旋转,则可以在animation属性中添加infinite参数,代码如下:
.close:hover::before{
-webkit-animation: spin 1s linear infinite;
animation: spin 1s linear infinite;
}
以上代码中,infinite参数表示动画将无限循环。如果我们只希望动画循环一定次数,则可以将其修改为相应的数字。例如,要使图标360度旋转两次,代码如下:
.close:hover::before{
-webkit-animation: spin 1s linear 2;
animation: spin 1s linear 2;
}
在速度曲线和播放次数之间还可以插入一个时间参数,用以设置动画延迟的时间。如希望使图标在1秒钟后再开始旋转,并旋转两次,代码如下:
.close:hover::before{
-webkit-animation: spin 1s linear 1s 2;
animation: spin 1s linear 1s 2;
}
我们还可以在animation动画中加入反向播放参数alternate。在加入该参数后,动画将在偶数次数时反向播放动画。如在之前代码中,图标将顺时针旋转两次,而加入alternate后,则变为顺时针旋转一次后,再逆时针旋转一次,代码如下:
.close:hover::before{
-webkit-animation: spin 1s linear 1s 2 alternate;
animation: spin 1s linear 1s 2 alternate;
}
animation动画序列
在以上的animation属性参数中,延迟参数是我们较为常用的一种参数。当动画的对象为多个时,我们常常用延迟参数来形成动画序列。如以下代码定义了5个不同的图标:
<span class="home icon">Home</span>
<span class="search icon">Search</span>
<span class="user icon">User</span>
<span class="mail icon">Mail</span>
<span class="chat icon">Chat</span>
图标的基本样式和之前的Close图标一致,不同之处在于此处的图标都设置为inline-block,使它们能够横向排列。代码如下:
.icon{
display:inline-block;
margin-right:20px;
}
.home::before{
content:"\e62e";
}
.search::before{
content:"\e630";
}
/*其余伪元素content属性设置略过*/
图标的初始显示效果如图所示。
接下来,为图标添加animation动画,使图标初始位置向下偏移-100%,然后再向上移动回到初始位置,在此过程中同时使图标由完全透明变化为完全不透明,代码如下:
.icon{
-webkit-animation:move 1s;
animation:move 1s;
}
@-webkit-keyframes move {
from {
opacity:0;
-webkit-transform:translateY(100%);
}
to {
opacity:1;
-webkit-transform:translateY(0%);
}
}
@keyframes move {
from {
opacity:0;
transform:translateY(100%);
}
to {
opacity:1;
transform:translateY(0%);
}
}
在以上代码中,我们使用了transform属性的translateY方法来实现图标的向下偏移,并使用opacity属性来设置图标的透明度。动画效果如图所示。
以上5个图标的动画效果都是同时进行的,为了使图标运动带有先后顺序,我们将为每个动画添加延迟。和之前运用的方法所不同,我们可以直接通过animation-delay属性来设置animation动画延迟,代码如下:
.home{
-webkit-animation-delay:0s;
animation-delay:0s;
}
.search{
-webkit-animation-delay:.1s;
animation-delay:.1s;
}
.user{
-webkit-animation-delay:.2s;
animation-delay:.2s;
}
.mail{
-webkit-animation-delay:.3s;
animation-delay:.3s;
}
.chat{
-webkit-animation-delay:.4s;
animation-delay:.4s;
}
在以上代码中,我们设置了5个图标的延迟时间分别为0、0.1、0.2、0.3和0.4s。实际上,延迟0秒为默认值,因此第一个图标实际上也不需要设置延迟代码。测试页面,动画效果如图所示。
“灵异”事件的解决之道
以上效果所呈现的延迟运画效果似乎已经非常完美,5个图标依次出现并向上运动到最终的位置。然而,当我们仔细看动画的整个过程,会发现在动画的最开头,几个图标将在顶部一闪而过,如图所示。
发生这种“灵异”事件的原因在于除第一个图标外,其余图标都有一定的动画延迟,而在动画没有开始时,图标是没有发生偏移,也是完全不透明的,只有当动画开始的那一瞬间,图标才会切换到完全透明且偏移的动画起始状态。
那么如何解决这一问题呢?或许我们可以尝试使5个图标默认状态就是发生偏移且完全透明的,但即使这样修改后,测试页面时我们会发现,动画开头的闪现问题消失了,而新的问题又发生了,当动画结束后,5个图标又回到了其默认状态,即全部消失不见了。
要解决这一问题,就需要使用animation动画的animation-fill-mode属性。这一属性规定了元素在动画时间之外的状态是怎样的。若该值为forwards,则表示动画完成后保留最后一个关键帧中的属性值,该值为backwards时则恰好相反,表示在动画延迟之前就使得元素应用第一个关键帧中的属性值,而该值为both时则表示同时包含forwards和backwards两种设置。在本例中,我们使用backward或both均可,代码如下:
.icon{
-webkit-animation-fill-mode:both;
animation-fill-mode:both;
}
现在,再次测试页面,图标的闪现问题就得到了完美的解决,如图所示。
速度曲线的设置
在animation中也可以像transition动画那样设置速度曲线。CSS3动画中默认的ease效果本来就很不错,因此我们往往省略了对于速度曲线的设置。而在一些非常自定义的动画中,我们也可以考虑运用速度曲线来实现一些特殊的效果。
例如,在本例中我们希望图标的运动带有一点弹性效果,即图标向上运动时,并非减速并停止在终点,而是到达终点后继续向上运动,超过一定距离后再反方向运动回到终点,形成一种往复的效果。我们当然可以使用帧动画来实现这样的效果,但是如果使用速度曲线将更为简便。要使用自定义曲线,我们往往需要一些工具,因为CSS3动画使用了三次贝塞尔(Cubic Bezier)数学函数来生成速度曲线,而这个函数的参数并不直观。我们可以使用诸如cubic-bezier.com这样的站点来可视化地调整速度曲线,如图所示。
在http://cubic-bezier.com中,我们可以通过拖动两个控制点来调整速度的曲率,最终生成的贝塞尔函数将依次包括两个控制点的x和y位置。其中x位置的范围在0和1之间,y位置则既可以在0和1之间,也可以大于或小于这个数值范围。
为了实现弹性效果,我们将第一个控制点拖动到(.62,-0.91)的位置,将第二个控制点拖动到(.45,1.97)的位置,形成的速度曲线如图所示。
接下来,我们就能够将该速度曲线写入animation属性的参数中,代码如下:
.icon{
-webkit-animation:move 1s cubic-bezier(.62,-0.91,.45,1.97);
animation:move 1s cubic-bezier(.62,-0.91,.45,1.97);
}
现在,测试页面,我们就能得到弹性的动画效果了,动画的结尾效果如图所示。