性能更好的js动画实现方式---requestAnimationFrame

用js来实现动画,我们一般是借助setTimeout或setInterval这两个函数,css3动画出来后,我们又可以使用css3来实现动画了,而且性能和流畅度也得到了很大的提升。但是css3动画还是有不少局限性,比如不是所有属性都能参与动画、动画缓动效果太少、无法完全控制动画过程等等。所以有的时候我们还是不得不使用setTimeout或setInterval的方式来实现动画,可是setTimeout和setInterval有着严重的性能问题,虽然某些现代浏览器对这两函个数进行了一些优化,但还是无法跟css3的动画性能相提并论。这个时候,就该requestAnimationFrame出马了。

requestAnimationFrame 是专门为实现高性能的帧动画而设计的一个API,目前已在多个浏览器得到了支持,包括IE10+,Firefox,Chrome,Safari,Opera等,在移动设备上,ios6以上版本以及IE mobile 10以上也支持requestAnimationFrame,唯一比较遗憾的是目前安卓上的原生浏览器并不支持requestAnimationFrame,不过对requestAnimationFrame的支持应该是大势所趋了,安卓版本的chrome 16+也是支持requestAnimationFrame的。

requestAnimationFrame 比起 setTimeout、setInterval的优势主要有两点:

1、requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。

2、在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。

像setTimeout、setInterval一样,requestAnimationFrame是一个全局函数。调用requestAnimationFrame后,它会要求浏览器根据自己的频率进行一次重绘,它接收一个回调函数作为参数,在即将开始的浏览器重绘时,会调用这个函数,并会给这个函数传入调用回调函数时的时间作为参数。由于requestAnimationFrame的功效只是一次性的,所以若想达到动画效果,则必须连续不断的调用requestAnimationFrame,就像我们使用setTimeout来实现动画所做的那样。requestAnimationFrame函数会返回一个资源标识符,可以把它作为参数传入cancelAnimationFrame函数来取消requestAnimationFrame的回调。怎么样,是不是也跟setTimeout的clearTimeout很相似啊。

所以,可以这么说,requestAnimationFrame就是一个性能优化版、专为动画量身打造的setTimeout,不同的是requestAnimationFrame不是自己指定回调函数运行的时间,而是跟着浏览器内建的刷新频率来执行回调,这当然就能达到浏览器所能实现动画的最佳效果了。

目前,各个支持requestAnimationFrame的浏览器有些还是自己的私有实现,所以必须加前缀,对于不支持requestAnimationFrame的浏览器,我们只能使用setTimeout,因为两者的使用方式几近相同,所以这两者的兼容并不难。对于支持requestAnimationFrame的浏览器,我们使用requestAnimationFrame,而不支持的我们优雅降级使用传统的setTimeout。把它们封装一下,就能得到一个统一兼容各大浏览器的API了。

代码可以到这里来查看:https://gist.github.com/chaping/88813f56e75b0fd43f8c

var lastTime = 0;
var prefixes = ‘webkit moz ms o‘.split(‘ ‘); //各浏览器前缀

var requestAnimationFrame = window.requestAnimationFrame;
var cancelAnimationFrame = window.cancelAnimationFrame;

var prefix;
//通过遍历各浏览器前缀,来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式
for( var i = 0; i < prefixes.length; i++ ) {
    if ( requestAnimationFrame && cancelAnimationFrame ) {
      break;
    }
    prefix = prefixes[i];
    requestAnimationFrame = requestAnimationFrame || window[ prefix + ‘RequestAnimationFrame‘ ];
    cancelAnimationFrame  = cancelAnimationFrame  || window[ prefix + ‘CancelAnimationFrame‘ ] || window[ prefix + ‘CancelRequestAnimationFrame‘ ];
}

//如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame,则会退到setTimeout
if ( !requestAnimationFrame || !cancelAnimationFrame ) {
    requestAnimationFrame = function( callback, element ) {
      var currTime = new Date().getTime();
      //为了使setTimteout的尽可能的接近每秒60帧的效果
      var timeToCall = Math.max( 0, 16 - ( currTime - lastTime ) );
      var id = window.setTimeout( function() {
        callback( currTime + timeToCall );
      }, timeToCall );
      lastTime = currTime + timeToCall;
      return id;
    };

    cancelAnimationFrame = function( id ) {
      window.clearTimeout( id );
    };
}

//得到兼容各浏览器的API
window.requestAnimationFrame = requestAnimationFrame;
window.cancelAnimationFrame = cancelAnimationFrame;

这样子我们就能在所有浏览器上使用requestAnimationFrame和cancelAnimationFrame了。

下面举个简单的例子来说明怎么运用requestAnimationFrame进行动画,下面的代码会将id为demo的div以动画的形式向右移动到300px

<div id="demo" style="position:absolute; width:100px; height:100px; background:#ccc; left:0; top:0;"></div>

<script>
var demo = document.getElementById(‘demo‘);
function rander(){
    demo.style.left = parseInt(demo.style.left) + 1 + ‘px‘; //每一帧向右移动1px
}
requestAnimationFrame(function(){
    rander();
    //当超过300px后才停止
    if(parseInt(demo.style.left)<=300) requestAnimationFrame(arguments.callee);
});
</script>
时间: 2024-10-01 22:23:36

性能更好的js动画实现方式---requestAnimationFrame的相关文章

性能更好的js动画实现方式&mdash;&mdash;requestAnimationFrame

用js来实现动画,我们一般是借助setTimeout或setInterval这两个函数,css3动画出来后,我们又可以使用css3来实现动画了,而且性能和流畅度也得到了很大的提升.但是css3动画还是有不少局限性,比如不是所有属性都能参与动画.动画缓动效果太少.无法完全控制动画过程等等.所以有的时候我们还是不得不使用setTimeout或setInterval的方式来实现动画,可是setTimeout和setInterval有着严重的性能问题,虽然某些现代浏览器对这两函个数进行了一些优化,但还是

性能更好的js动画实现方式——requestAnimationFrame

本文转载,原文地址:http://www.cnblogs.com/2050/p/3871517.html 用js来实现动画,我们一般是借助setTimeout或setInterval这两个函数,css3动画出来后,我们又可以使用css3来实现动画了,而且性能和流畅度也得到了很大的提升.但是css3动画还是有不少局限性,比如不是所有属性都能参与动画.动画缓动效果太少.无法完全控制动画过程等等.所以有的时候我们还是不得不使用setTimeout或setInterval的方式来实现动画,可是setTi

js动画最佳实现——requestAnimationFrame

我们经常用setInterval来实现动画,其实这种做法不是太好,因为不同浏览器的刷新频率也不一样(一般认为设置16为最佳,按每秒60帧算,1000/60≈16.67) var dis = 0,timer = 0; clearInterval(timer); timer = setInterval(function(){ div.style.left = ++dis; if(dis>=50) clearInterval(timer) },16) 实现js动画最好的是requestAnimatio

js 动画方法之requestAnimationFrame

js动画实现的方法到现在有三种 1 css3: 通过animattion+keyframes;或 transition 2. setTimeout/setInterval: setTimeout/setInterval:通过递归调用同一方法来不断更新动画元素以达到动起来的效果,动画过度绘制,浪费 CPU 周期以及消耗额外的电能等问题. 3.requestAnimationFrame: requestAnimationFrame:是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用

关于JS动画和CSS3动画的性能差异

本文章为综合其它资料所得. 根据Google Developer,Chromium项目里,渲染线程分为main thread和compositor thread.如果CSS动画只是改变transforms和opacity,这时整个CSS动画得以在compositor thread完成(而JS动画则会在main thread执行,然后触发compositor进行下一步操作)在JS执行一些昂贵的任务时,main thread繁忙,CSS动画由于使用了compositor thread可以保持流畅,可

CSS VS JS动画,哪个更快[译]

英文原文:https://davidwalsh.name/css-js-animation 原作者Julian Shapiro是Velocity.js的作者,Velocity.js是一个高效易用的js动画库.在<Javascript网页动画设计>一书中对这个库有很多更具体的剖析,对Velocity及JS动画感兴趣的可以一看. 基于Javascript的动画怎么可能总是和 CSS transition 一样快,甚至更快呢?到底是什么秘密呢?Adobe 和 Google 是怎么做到让他们的富媒体移

CSS vs JS动画:谁更快?

CSS vs JS动画:谁更快? 2016-05-16 前端大全 (点击上方公众号,可快速关注) 英文:Julian Shapiro 译者:MZhou's blog 链接:http://zencode.in/19.CSS-vs-JS动画:谁更快?.html 这篇文章翻译自 Julian Shapiro 的 CSS vs. JS Animation: Which is Faster?.Julian Shapiro 也是 Velocity.js 的创造者.这是一个非常高效.简单易用的JS动画库.他在

How Javascript works (Javascript工作原理) (十三) CSS 和 JS 动画底层原理及如何优化其性能

个人总结:读完这篇文章需要20分钟. 这是 JavaScript 工作原理的第十三章. 概述 正如你所知,动画在创建令人叹服的网络应用中扮演着一个关键角色.由于用户越来越注重用户体验,商户开始意识到完美,令人愉悦的用户体验的重要性,结果网络应用变得越来越重并且拥有更多动态交互的功能.这就要求网络应用提供更加复杂的动画来实现平滑的状态过渡贯穿于用户的使用过程当中.现在,这已经司空见惯.用户变得越来越挑剔,他们潜意识期许可以获得快速响应和良好交互的用户界面. 然而,让界面具有动画效果不一定是件简单的

web 动画实现方式

这这里,总结了一些 我知道的不用框架来实现动画的方式,总的来说有两种,第一种是用css的transition或keyframes+animation,第二种用js来实现 首先看基本结构 <style> div { position: relative; background: #999; width: 50px; height: 50px; } .ani { } </style> <body> <div class="ani"></