Transition动画学习

利用css3的动画技术,我们可以实现很多绚丽的动画,作为初学者来说,我们可以从最简单的动画学习开始,本节我想跟大家一起学习的是css3中的transition动画和如何使用JavaScript来模拟实现同样的动画效果。

W3C对css transition 的定义是允许css属性值在指定的持续时间内发生平滑地变化。而mozilla上介绍它是transition-property, transition-duration, transition-timing-function和transition-delay的简写属性,它允许定义一个元素两个状态之间的过渡过程。不同的状态可以通过像:hover或:active这样的伪类来定义,还可以使用JavaScript来动态地设置。

transition
语法:[<’transition-property’>||<’transition-duration’>||<’transition-timing-function’>|| <transition-delay>[,[<’transition-property’>||<’transition-duration’>||<’transition-timing-function’> || <transition-delay>] ]*

由于transition是一个简写属性,它没有初始值,但是它所代表的四个属性都有初始值:
1) transition-property: all 表示元素所有属性值发生改变时都会执行transition效果。
它还可以取值none,表示没有属性发生改变,或者指定元素属性名表示某属性发生改变。
2) transition-duration: 0s 表示动画的持续时间是0s, 也即是实时的。
它还可以取值为其他的数字类型,表示动画的持续时间为多少秒。
3) transition-timing-function: ease 表示元素属性值改变的速率是逐渐变慢的。
它还可以取值linear(匀速)、ease-in(加速)、ease-out(减速)、ease-in-out(加速再减速) cubic-bezier(自定义时间曲线)来指定动画改变属性值的速率。
Ÿ4) transition-delay: 0s 表示元素执行动画的延迟时间为0s, 即立即执行,没有延时。它还可以取值为其他的数字类型,表示动画延迟多少秒执行。

来看下面简单的html和css代码示例:

  1. <div style="height:150px;">
  2.   <h2><span></span>热门网站</h2>
  3.     <ul>
  4.       <li><a href="http://info.3g.qq.com/g/s?aid=index&g_f=2543">腾讯</a></li>
  5.       <li><a href="http://m.sohu.com/?_trans_=000012_qq_dh">搜狐</a></li>
  6.       <li><a href="http://3g.163.com/links/3810">网易</a></li>          
  7.     </ul>
  8. </div>
  1. .main{ overflow:hidden; -webkit-transition: all 0.5s ease-in 0s; -moz-transition: all 0.5s ease-in 0s;
  2. -o-transition: all 0.5s ease-in 0s; transition: all 0.5s ease-in 0s; background:#fff;}
  3. .main .close{ height:0!important;}
复制代码

上面代码会使得类名为main的div元素的所有属性值中任何一个发生改变时,如height属性由150px变为0时(可通过将”main”类名修改为”main close”实现)执行transition动画效果,动画持续时间为0.5s,属性值的改变速率为加速,延迟时间为0s,即立即执行。当然,div元素的height属性由0变为150px时同样会自动执行该动画。考虑到该属性的标准还没有稳定下来,不同的浏览器对它的支持都需要加上对应的前缀,比如像chrome和safari这样的基于webkit内核的浏览器需要添加-webkit作为前缀。

setTimeout & setInterval
setTimeout和setInterval是JavaScript中的定时器,并且有着本质的区别。
setTimeout(callback, time)会初始化一个计时器,在指定的时间间隔time毫秒后执行回调函数callback,而setInterval(callback, time)也会初始化一个计时器,但是它是每隔指定的时间间隔time毫秒后就循环执行回调函数callback。它们都会返回一个唯一的标志ID(Number类型),可以用这个ID来取消计时器。取消的方法是调用clearTimeout(id)和clearInterval(id)方法。

我们用一个简单的示例就能说明setTimeout与setInterval之间的区别:

  1. setTimeout(function(){
  2.   //do something in callback
  3.   setTimeout(arguments.callee, 100);
  4. }, 100);
  1. setInterval(function(){
  2.   //do something in callback
  3. }, 100);

初看起来,它们实现的功能都是每隔100ms后循环执行回调函数直至取消掉计时器,但实际上,它们有着本质的不同。setTimeout回调函数的执行和上一次回调函数的执行的时间间隔至少为100ms,因为还需要加上回调函数的执行时间(JavaScript的单线程排队机制会强制异步事件在队列中排队等待执行)。而setInterval则总是会每过100ms尝试执行一次回调,它不管上一次回调是什么时候执行的,当然,如果回调函数的执行时间比指定的延时长,那么它们将连续地执行而没有延时。

如果你想利用setTimeout实现一个简单的动画,方法很简单:

  1. function animate(){
  2.   //do something
  3.   setTimeout(animate, 100);
  4. }
  5. setTimeout(animate, 100);

当然,你很可能还需要加一些诸如动画持续时间,属性改变范围等的逻辑控制。

requestAnimationFrame
setTimeout或setInterval虽然能够实现动画效果,但流畅性体验不够高,浏览器之后提供的另一个统一帧管理的API requestAnimationFrame能够实现更高效的js动画效果。

requestAnimationFrame方法会告诉浏览器你想执行一个动画,并请求浏览器提前安排下一帧动画需要显示时浏览器窗口的重绘,该方法接收一个回调函数,该回调函数会在下一帧动画开始时,窗口被重绘前自动被调用。当然,在你的回调函数中,你必须重新调用requestAnimationFrame方法,除非你想停止动画的执行。该回调函数只会被传入一个参数,该参数表明了下一次的动画帧将在何时显示。

下面就让我们一起通过一个简单的代码示例来学习下。

  1. var requestAnimationFrame = window.requestAnimationFrame
  2.             || window.mozRequestAnimationFrame
  3.             || window.webkitRequestAnimationFrame
  4.             || window.msRequestAnimationFrame
  5.             || window.oRequestAnimationFrame
  6.             || function(callback) {setTimeout(callback, 17);};
  7. animate(0, 300, 500);
  8. function animate(from, to, time) {
  9. var startTime = Date.now();
  10.   function go(timestamp) {
  11.     timestamp = timestamp || Date.now();
  12.     var progress = timestamp - startTime;
  13.     if (progress >= time) {
  14.       window.scrollTo(0, to);
  15.         return;
  16.     }
  17.     if(from<to){
  18.       var now = (to - from) * (progress / time);
  19.     }else{
  20.       var now = from - (from - to) * (progress / time);
  21.     }
  22.     window.scrollTo(0, now);
  23.     requestAnimationFrame(go);
  24.   }
  25.   requestAnimationFrame(go);
  26. }

上述代码利用js模拟实现了页面滑动的动画,调用animate(0, 300, 500)表示页面会从(0,0)位置滑动到(0, 300)位置,动画会在500ms内完成,你可以看到一个页面滑动的过程。具体的实现逻辑是:调用requestAnimationFrame函数,传递一个回调参数go,在下一个动画帧时,即需要重新绘制动画时,会调用go()函数并执行。go()函数中主要是设置好页面每帧应该滚动的距离并通过window.scrollTo()实现滚动,另外,还需判断距离开始执行动画的时间startTime的时间间隔progress是否超过动画持续时间time(调用animate时设为500毫秒),如果没有超过,则一直循环调用requestAnimationFrame函数,则下一动画帧时会自动调用回调函数go(),如果超过,表明希望动画结束执行,执行完window.scrollTo(0, to)将页面滑动到最终希望停留的位置即返回。

关于timestamp参数,就不得不提不同的浏览器的不同实现了,mozilla实现时,传递给mozRequestAnimationFrame()方法的函数实际是一个下一次重绘何时发生的时间码(以毫秒为单位从1970年1月1日算起),也即timestamp参数的意义,我们可以通过计算它与动画开始执行的时间startTime的时间间隔来控制动画的持续时间。但是,基于webkit内核的chrome浏览器在实现webkitRequestAnimationFrame()方法时并不会通过回调函数传递时间码,也就说明你无法知道下一次重绘何时发生。所以上面示例代码在chrome上实现时最好不要传timestamp参数。

posted @ 2014-11-13 14:02  脾气不坏  阅读(129)  评论(0)    收藏  举报