用js来实现动画,我们一般是借助setTimeout或setInterval这两个函数,css3动画出来后,我们又可以使用css3来实现动画了,而且性能和流畅度也得到了很大的提升,但是css3动画还是有不少局限性,所以有的时候我们还是不得不使用setTimeout或setInterval的方式来实现动画,可是setTimeout和setInterval存在严重的性能问题,虽然某些现代浏览器(现代浏览器指该浏览器能够理解和支持HTML和XHTML,Cascading Style Sheets(CSS),ECMAScript及W3C Document Object Model(DOM)标准。)对这两函个数进行了一些优化,但还是无法跟css3的动画性能相提并论。这个时候,就该requestAnimationFrame出马了。但是目前并不是所有浏览器都支持。requestAnimationFrame 是专门为实现高性能的帧动画而设计的一个API,目前已在多个浏览器得到了支持,包括IE10+,Firefox,Chrome,Safari,Opera等,在移动设备上,ios6以上版本以及IE mobile 10以上也支持requestAnimationFrame,唯一比较遗憾的是目前安卓上的原生浏览器并不支持requestAnimationFrame,不过对requestAnimationFrame的支持应该是大势所趋了,安卓版本的chrome 16+也是支持requestAnimationFrame的。
css3动画局限性:
一、不是所有属性都能参与动画
二、动画缓动效果太少
三、无法完全控制动画过程
requestAnimationFrame 比起 setTimeout、setInterval的优势主要有两点:
一、requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。
二、在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。
跟setTimeout、setInterval一样,requestAnimationFrame也是一个全局函数。调用requestAnimationFrame后,它会要求浏览器根据自己的频率进行一次重绘(repaints),它接收一个回调函数作为参数,在即将开始的浏览器重绘时,会调用这个函数,并会给这个函数传入调用回调函数时的时间作为参数。由于requestAnimationFrame的功效只是一次性的,所以若想达到动画效果,则必须连续不断的调用requestAnimationFrame,这就跟setTimeout的效果是一样的。requestAnimationFrame函数会返回一个资源标识符,可以把它作为参数传入cancelAnimationFrame函数来取消requestAnimationFrame的回调。这就跟setTimeout的clearTimeout是相似的。
requestAnimationFrame就是一个性能优化版、专为动画量身打造的setTimeout,不同的是requestAnimationFrame不是自己指定回调函数运行的时间,而是根据浏览器内建的刷新频率来执行回调,这就能达到浏览器所能实现动画的最佳效果了。但是目前,支持requestAnimationFrame的浏览器有些还是自己的私有实现,所以必须加前缀,对于不支持requestAnimationFrame的浏览器,我们只能使用setTimeout,因为两者的使用方式几近相同,所以这两者的兼容并不难。对于支持requestAnimationFrame的浏览器,我们使用requestAnimationFrame,而不支持的我们优雅降级使用传统的setTimeout。把它们封装一下,就能得到一个统一兼容各大浏览器的API了。
浏览器可以将并发动画优化为单个回流和重绘周期,从而实现更保真度的动画。例如,基于JS的动画与CSS转换或者SVG SMIL步。另外,如果在不可见的选项卡中运行动画循环,浏览器将无法运行,这就意味着较少的CPU,GPU和内存使用量。使用JavaScript的Internet Explorer 10 和windows 应用程序引入了对requestAnimationFrame方法的支持,该方法通过在系统准备好绘制框架时调用动画框架,提供更平滑和更高效的方式来创建动画网页。使用setTimeout和setInterval绘制动画没有提供一种有效的方法来为动画安排图形计时器,这就导致了动画透支,浪费CPU周期还有额外的功率使用。此外即使在网站不可见的情况下也经常发生动画,特别是在当网站使用后台选项卡的页面或者浏览器最小化时。
此外requestAnimationFrame方法可以解决丢帧的问题,因为它在使用应用程序时通知浏览器需要更新页面显示,因此,应用程序与浏览器绘画间隔完全一致,并且只使用适当的资源量。并且从setTimeout切换到requestAnimationFrame很容易,因为他们都调度单个回调,对于继续动画,在动画函数被调用后再次调用requestAnimationFrame于继续动画,在动画函数被调用后再次调用requestAnimationFrame。