巧用CSS3动画与精灵图制作关键帧动画

1,820 阅读5分钟
原文链接: www.shuaihua.cc

这篇主要介绍CSS3中animation动画属性的animation-timing-function属性,并不会介绍CSS3的animation全部特性,如需了解CSS3的animation属性完整的使用技巧,可以看之前写的这一篇 玩转有趣的 CSS3 Animation 动画

巧用CSS3的keyframes与精灵图制作非GIF关键帧动画

默认的,当我们想要使用CSS3的@keyframes特性创建一个动画时,你还记得它的缓动值是什么吗?

如果单独设置animation属性属性的每一个值,缓动属性指的就是 animation-timing-function,从上图中可发现,该缓动属性的默认值是 ease,也就是从淡入到淡出的缓动值。

下面看一个例子:

从红色到蓝色的动画。

下面是源代码,为了方便期间,这里不采用符合属性,而将属性拆分开并单独罗列,以便于分析。

.box1{
    width:100px;
    height:100px;
    animation-name: box1;
    animation-duration: 1s;
    animation-timing-function:ease;
    animation-iteration-count:infinite;
  }
  @keyframes box1{
    0%{
      background:#ff0000;
    }
    50%{
      background:#00ff00;
    }
    100%{
      background:#0000ff;
    }
  }

从上面的例子中能看到非常平缓的颜色过渡效果。这就是将animation-timing-function设置为 ease 的效果。

再来看下animation-timing-function一些可能的值:

/* Keyword values */
animation-timing-function: ease;
animation-timing-function: ease-in;
animation-timing-function: ease-out;
animation-timing-function: ease-in-out;
animation-timing-function: linear;
animation-timing-function: step-start;
animation-timing-function: step-end;

/* Function values */
animation-timing-function: cubic-bezier(0.1, 0.7, 1.0, 0.1);
animation-timing-function: steps(4, end);
animation-timing-function: frames(10);

/* Multiple animations */
animation-timing-function: ease, step-start, cubic-bezier(0.1, 0.7, 1.0, 0.1);

/* Global values */
animation-timing-function: inherit;
animation-timing-function: initial;
animation-timing-function: unset;

我试着使用不同的animation-timing-function属性值,看一下他们之间的区别:

首先定义相同的@keyframes规则:

@keyframes box2{
    0%{
      background:#ff0000;
      transform:scale(0,0) translate(0px,0px);
    }
    50%{
      background:#00ff00;
      transform:scale(1,1) translate(100px,0px);
    }
    100%{
      background:#0000ff;
      transform:scale(1,1) translate(0px,0px);
    }
  }

① 使用step-start属性值:

.box2-1{
    width:70px;
    height:70px;
    border-radius:50%;
    animation-name: box2;
    animation-duration: 1s;
    animation-timing-function:step-start;  //step-start
    animation-iteration-count:infinite;
  }

② 使用step-end属性值:

.box2-2{
    width:70px;
    height:70px;
    border-radius:50%;
    animation-name: box2;
    animation-duration: 1s;
    animation-timing-function:step-end;  //step-end
    animation-iteration-count:infinite;
  }

③ 使用steps()属性值:

.box2-3{
    width:70px;
    height:70px;
    border-radius:50%;
    animation-name: box2;
    animation-duration: 1s;
    animation-timing-function:steps(2,start);  //steps()
    animation-iteration-count:infinite;
  }

④ 使用ease属性值:

.box2-4{
    width:70px;
    height:70px;
    border-radius:50%;
    animation-name: box2;
    animation-duration: 1s;
    animation-timing-function:ease;  //ease
    animation-iteration-count:infinite;
  }

⑤ 使用ease-in属性值:

.box2-5{
    width:70px;
    height:70px;
    border-radius:50%;
    animation-name: box2;
    animation-duration: 1s;
    animation-timing-function:ease-in;  //ease-in
    animation-iteration-count:infinite;
  }

⑥ 使用ease-out属性值:

.box2-6{
    width:70px;
    height:70px;
    border-radius:50%;
    animation-name: box2;
    animation-duration: 1s;
    animation-timing-function:ease-out;  //ease-out
    animation-iteration-count:infinite;
  }

⑦ 使用ease-in-out属性值:

.box2-7{
    width:70px;
    height:70px;
    border-radius:50%;
    animation-name: box2;
    animation-duration: 1s;
    animation-timing-function:ease-in-out;  //ease-in-out
    animation-iteration-count:infinite;
  }

⑧ 使用linear属性值:

.box2-8{
    width:70px;
    height:70px;
    border-radius:50%;
    animation-name: box2;
    animation-duration: 1s;
    animation-timing-function:linear;  //linear
    animation-iteration-count:infinite;
  }

⑨ 使用cubic-bezier()属性值:

.box2-9{
    width:70px;
    height:70px;
    border-radius:50%;
    animation-name: box2;
    animation-duration: 1s;
    animation-timing-function: cubic-bezier(0.1, 0.7, 1.0, 0.1);  //cubic-bezier()
    animation-iteration-count:infinite;
  }

我想借助animation属性,将一组静态格式的序列图片按照一定时间间隔播放,看起来就像GIF图一样,从上面的示例来看,实现这一效果,首选就是 steps() 属性值,因为这个属性值能将动画的过程切分成长度相同的时间间隔,就像是逐帧动画,我只要将动画规则设置为改变背景图像的background-position属性值,就能实现在不适用gif图的前提下实现动画。

说干就干,首先我需要准备一组序列图。

上方是一张从网络中下载的gif图片

我从网上下载了一张gif图,然后将其放入ps中处理,得到我想要的象sprite那样的一张静态序列图。

拖入PS中后可以看到这张gif图一共有12帧,我将这些帧小心的排列成一行或一列;

将其导出为静态图片,任意格式,此时可以在图片大小、质量与占用空间上做权衡,最终我选择将其导出为jpg格式的,宽度为1920,高度为90的横向序列的图片。

在进入正式的animation实现动画之前,我需要知道整张序列图中每一张小图的宽高,好在后续设置背景图像容器的宽高,还需要知道这张序列图一共有几张小图,前期已经知道了共有12张小图:

排列方式:横向排列
大图宽度:1920px
大图高度:90px
小图个数:12 (个)
小图宽度:1920 / 12 = 160 (px)

知道这些参数后,就可以进入CSS3的书写环节:

<style>
@keyframes move-jpg{
  0%{
    background-position: 0px 0px;
  }
  100%{
    background-position: -1920px 0px;
  }
}

.move-jpg{
  width:160px;
  height:90px;
  background-image:url(/public/article/1511946406127/sucai.jpg);
  animation-name: move-jpg;
  animation-duration: 1s;
  animation-timing-function: steps(12,end);
  animation-iteration-count:infinite;
}
</style>

我在定义一个div标签用来播放动画:

<div class="move-jpg"></div>

OK~下面这张图片就是最终效果:

我可以很方便的调节播放时长、关键帧数量,只需要调节animation-duration和animation-timing-function两个属性值即可。

还可以使用animation-iteration-count属性设置播放次数,这次我设置的 infinite ,即永远播放,还可以设置 1、2、3...

还可以设置animation-direction,规定播放方向,可选的属性值:

animation-direction: normal
animation-direction: reverse
animation-direction: alternate
animation-direction: alternate-reverse
animation-direction: normal, reverse
animation-direction: alternate, reverse, normal

设置alternate可以正向播放完再反向交替播放。

比卡丘显示开心的表情,然后反向播放就是疑惑的表情


参考资料:animation-MDN