CSS3动画浅谈

在做web页面的时候,难免会用到一些动画缓动,过去我们大部分都是用js来对web元素的移动来进行控制,但是,自从h5 和 css3的出现,让我们有了一个新的选择。

css3动画与传统的js动画的比较

1.两者实现的原理

说到css3动画,我们肯定要将它与我们在web中使用的最多的js动画来作比较。其实就其本质而言,两者都同样是对html元素进行操作,同样是改变dom节点的css参数,来起到动画的效果。但是,在效率方面两者还是存在一定的差距的。

这里我们可以参考下:

根据Google Developer,Chromium项目里,渲染线程分为main thread和compositor thread。

如果CSS动画只是改变transforms和opacity,这时整个CSS动画得以在compositor thread完成(而JS动画则会在main thread执行,然后触发compositor进行下一步操作)

在JS执行一些昂贵的任务时,main thread繁忙,CSS动画由于使用了compositor thread可以保持流畅,可参考adobe的博客。

在主线程中,维护了一棵Layer树(LayerTreeHost),管理了TiledLayer,在compositor thread,维护了同样一颗LayerTreeHostImpl,管理了LayerImpl,这两棵树的内容是拷贝关系。因此可以彼此不干扰,当Javascript在main thread操作LayerTreeHost的同时,compositor thread可以用LayerTreeHostImpl做渲染。当Javascript繁忙导致主线程卡住时,合成到屏幕的过程也是流畅的。

为了实现防假死,鼠标键盘消息会被首先分发到compositor thread,然后再到main thread。这样,当main thread繁忙时,compositor thread还是能够响应一部分消息,例如,鼠标滚动时,加入main thread繁忙,compositor thread也会处理滚动消息,滚动已经被提交的页面部分(未被提交的部分将被刷白)。

这里我们可以大概的了解到,js对web动画的执行,主要是在main thread中,而css3则是在compositor thread中,两者相比起来,main thread所承载的所有的js的逻辑,所以对于main thread中来说,资源是更加宝贵的。而在css3中,由于我们最常用的transform和opactiy动画,都是只要再compositor thread中来完成,大大的减轻了main thread 的压力,这也能让浏览器,更流畅的去表现一些效果。

但是,当css的动画改变了一些节点的结构时,那么同样的,这个动作会进入到main thread中进行重新的布局和渲染,这个时候哪怕是css3动画,同样也会对后续的操作进行阻塞,也就违背了我们使用css3动画的原则,这是我们尤其要注意的。

这里看看有哪些操作是会不进入到main thread的,也就是使用下面的动画变换时,使用css会来的更划算:

  • backface-visibility
  • opacity
  • perspective
  • perspective-origin
  • transfrom
2.使用场景

每一种技术的产生与兴起,都是为了去解决一类问题,但是肯定是无法解决所有问题的,所以,在什么情况下使用css3动画,什么时候使用js来实现动画,需要我们根据实际的情况来选择。

比如:一个web站点,其中有一部分的功能是响应用户操作后的盒子移动。而且需要兼容比较低版本的浏览器,这个时候可能我们优先会选择js动画。如果只是一个简单图片移动,或者简单的循环透明度循环,而且不需要兼容低版本的ie浏览器,那我们会选择css3动画。

在使用css3动画时,我们首先要知道,在对浏览器的支持方面,js来做动画可能适应的范围更广一点,虽然现在的浏览器对h5的支持力度越来越大,但是考虑到不同的兼容条件,对动画实现方式的选择自然也是不同。

css3动画的实现

1.简单入门css3动画

先看一个最简单的移动示例:

image

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
#box { width: 150px; height: 150px; background: red; float:left; margin-left: 500px;;animation:box-move 3s;}

@keyframes box-move{
0% {margin-left: 0px;}
100% {margin-left: 500px;}
}
</style>
</head>
<body>
<div id="box"></div>
</body>
</html>

css3动画和js动画的实现本质上都是通过改变盒子中的位置,大小,角度数值,通过不断刷新来使人感觉到盒子的各种各样的动画变换。这个实例中也是这样体现的。通过keyframes来定义一个动画的名称,然后将动画的表现写在里面,最后通过设置box animation样式来实现动画的播放。

不过有一点要注意,虽然我们在box-move这个动画中,最终定义了100%(结束为止)为margin-left:500px,但是如果在box中我们没有将margin-left的值设定为动画结束的位置,那么这个动画播放结束后,会回到box的初始位置中去。

如果不是很理解,可以将box中的margin-left属性删除,或者改为其他数值,能很快看到和之前表现的差异。

同理,不仅仅可以实现位置的动画,联通旋转,透明度的变化,css3都可以很好的表现:

image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
#box { width: 150px; height: 150px; background: red; float:left; margin-left: 500px;animation:box-move 3s; opacity: 1;transform:rotate(45deg);}

@keyframes box-move{
0% {margin-left: 0px; opacity: 0;transform:rotate(0deg);}
100% {margin-left: 500px; opacity: 1;transform:rotate(45deg);}
}
</style>
</head>
<body>
<div id="box"></div>
</body>
</html>

当然我也可以在keyframes boxmove中加入更多的帧,来控制整个动画的不同表现,例如下面我们就在keyframes中加入了一个50%,以此来控制当执行到一半时的各个动画参数。

1
2
3
4
5
6
7
8
9
<style>
#box { width: 150px; height: 150px; background: red; float:left; margin-left: 500px;animation:box-move 3s; opacity: 1;transform:rotate(45deg);}

@keyframes box-move{
0% {margin-left: 0px; opacity: 0;transform:rotate(0deg);}
50%{ margin-left: 300px; opacity: 0.5;transform:rotate(90deg);}
100% {margin-left: 500px; opacity: 1;transform:rotate(45deg);}
}
</style>

关于css3动画的更多使用api推荐大家去自行百度w3c上关于css3 animation的使用方式,我这里就不一一介绍,一看就明白,真的不难。

2.加强交互功能

可能有过一些前端经验的同学会发现,因为css3的动画都是写死在了各种样式表之中,那么在响应用户操作方面,肯定会有很大的不足。实际情况也确实如此。但是,我们可以通过javascript来控制动画的表现。(以下的实例依托于jqeury)

现在我们将在响应用户点击之后再开始执行动画:

image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<script src="http://libs.baidu.com/jquery/1.11.1/jquery.min.js"></script>
<style>
#box { width: 150px; height: 150px; background: red; float:left;opacity: 0;}

.box-move{ animation:box-move 3s;transform:rotate(45deg);margin-left: 500px;opacity: 1;}
@keyframes box-move{
0% {margin-left: 0px; opacity: 0;transform:rotate(0deg);}
100% {margin-left: 500px; opacity: 1;transform:rotate(45deg);}
}
</style>
</head>
<body>
<div id="box"></div>
</body>

<script>
$(function(){
$(document).click(function(){
$("#box").addClass("box-move");
});
});

</script>
</html>

这样我们通过js来响应点击,添加设定好的动画类”.box-move”来确定动画执行的时间。

小小的总结

还是那句话,所有的解决方案都不是一劳永逸的。学习css3的动画实现并不能解决一切问题,但是在特定环境下,会给我们提供很好的帮助。这里只是简单说明一下css3动画与js动画的异同与简单实现。如果需要解决更加复杂的问题,还需要我们更多的实践。谢谢。