大概半年前,无意中在网上看到一个新的js函数requestAnimationFrame,据说,此函数可以优化传统的js动画效果,似乎是未来js动画的新方向。

当时我所在的项目正好用到了和js动画有关的技术,于是在网上查阅了一些相关资料。虽然国内外都有人写过一些关于这个js函数的文章,但大多都只是简要说明工作原理,使用方式等等,一直都没有找到验证其优势所在的示例。

今天我就自己写两个testcase验证requestAnimationFrame的优势所在。

关于requestAnimationFrame这个函数在MDN上的说明是“告诉浏览器,你想要执行一个动画,该请求要求浏览器提前安排一下下一帧动画显示时需要进行的浏览器窗口的重绘”。也就是说,调用这个api就表示告诉浏览器,下次重绘页面时,记得执行我刚刚传给你的那个逻辑。

这样做一个最大的好处就是可以避免不必要的过度重绘,关于过度重绘的产生原因MSDN上已经说得很清楚了。

于是,我的测试思路是,用js构造若干个独立的动画,每个动画都有一个定时器去控制动画的执行,动画的效果就是通过修改一个div的位置坐标,使该div围绕一点做圆周运动。

定时器用两种不同的方式实现,一种用传统的setTimeout函数,每个20ms触发一次重绘逻辑。另一种用requestAnimationFrame触发重绘逻辑。(代码见文末)

下面两幅图为同时运行1500个动画,分别使用requestAnimationFrame和setTimeout时的效果:

使用 setTimeout

使用 requestAnimationFrame

下表为在不同的动画数目情况下,使用requestAnimationFrame和setTimeout时浏览器的渲染帧数对比,单位:FPS

Animation count

500

600

700

800

900

1000

1100

1200

1300

1400

1500

reqestanimationframe

30

30

28

26

20

20

20

20

19

17

15

setTimeout

34

32

29.5

27

25.5

21.8

19.7

16

14.7

13.1

12

由上表可以看出,当animation count大于1100的时候,使用requestAnimationFrame的性能是要优于使用setTimeout的,可是当animation count小于1000的时候,使用requestAnimationFrame的性能反而要差于用传统的setTimeout

同时,在上面的测试案例中,无论动画数目是多少,我们使用setTimeout时的延迟间隔始终都是20ms,但在一些情况下适当增加这个时间间隔,setTimeout函数还能得到更好的效果。比如当animation count为1100时,如果把这个间隔调整到40ms,浏览器的帧率可以达到25.5 FPS,明显优于使用requestAnimationFrame时的20 FPS。

看到这里估计大家和我一样都很失望吧,这个传说中实现了各种优化的新api怎么表现如此差强人意呢?

结合上次我写的关于统一帧管理的blog《使用统一帧管理优化前端性能》,我又想到另一种测试场景。

仍然是用js构造若干个独立的动画,但所有这些动画都共用同一个定时器去定时更新自己的状态并重绘,详见代码中的“test case 02”部分。

还是贴两幅同时运行1500个动画,分别使用requestAnimationFrame和setTimeout时的效果:

使用 setTimeout

使用 RequestAnimationFrame

同时附上不同的动画数目情况下,使用requestAnimationFrame和setTimeout时浏览器的渲染帧数对比,单位:FPS

Animation count

500

600

700

800

900

1000

1100

1200

1300

1400

1500

reqestanimationframe

30

30

30

30

29.5

28

20

20

20

20

20

setTimeout

37.5

35

34.4

32

31.5

29.5

29

26.5

25

24.3

23

由上表可见,当使用一个定时器控制所有动画的时候,使用setTimeout函数在各种动画数目场景下,其效果均优于使用requestAnimationFrame函数。

通过上面的两个测试案例,我们可以看到requestAnimationFrame函数似乎并不像大家所想的那样能给js动画带来性能上的大幅提升。虽然MDN和MSDN上对这个api的原理说明都让我觉得它确实是有用的,但实际测试的效果却并不能让我满意。也许各大浏览器厂商还会继续优化这个api的实现,使其能真正达到预期的效果吧。

BTW,其实到这里我自己都很怀疑是不是我的测试案例有问题?如果大家对测试案例有任何意见或建议,还请不吝赐教啊!

以上所有测试的运行环境为 Windows 7 Ultimate sp1 x64 + Chrome 25.0.1364.97 + Intel Core i3 530(2.93GHz) + 4G RAM

代码

 <!DOCTYPE html>
<html>
<head>
<style type="text/css">
html,body{height:100%;width:100%}
div{width:20px;height:20px;background-color:black;position:absolute;display:inline-block}
</style>
</head>
<body>
<div id="content" style="height:100%;width:100%;background-color:#979797;overflow:hidden;position:relative"></div>
<script type="text/javascript">
var cArray = new Array(); for (var i = 0; i < 1500; i++) {
var x = parseInt(Math.random() * document.body.clientWidth);
var y = parseInt(Math.random() * document.body.clientHeight);
var id = newGuid();
content.innerHTML += '<div id="' + id + '"></div>';
cArray.push(new Clock(x, y, 100, id));
} function Clock(x, y, r, id) {
this.start = new Date();
this.r = r;
this.x = x;
this.y = y;
this.offsetX = r;
this.offsetY = 0;
this.id = id;
this.draw = function(){
//update data
var timespan = new Date() - this.start;
var offsetR = ((timespan % 36000) % 720) / 360 * Math.PI;
this.offsetX = this.r * Math.cos(offsetR);
this.offsetY = this.r * Math.sin(offsetR);
//draw
var dom = document.getElementById(this.id);
dom.style.left = this.x + this.offsetX + 'px';
dom.style.top = this.y + this.offsetY + 'px'; //var that = this; //test case 01
//setTimeout(function(){that.draw()}, 40); //test case 01 - 1
//requestAnimationFrame(function(){that.draw()}); //test case 01 - 2
}
//this.draw(); //test case 01
} function renderLoop(){
for (var i = 0; i < cArray.length; i++) {
cArray[i].draw();
}
//setTimeout(renderLoop, 20); //test case 02 - 1
requestAnimationFrame(renderLoop); //test case 02 - 2
}
renderLoop(); //test case 02 function newGuid() {
var guid = "";
for (var i = 1; i <= 32; i++) {
var n = Math.floor(Math.random() * 16.0).toString(16);
guid += n;
if ((i == 8) || (i == 12) || (i == 16) || (i == 20))
guid += "-";
}
return guid;
}
</script>
</body>
</html>

如需转载,请注明转自 http://www.cnblogs.com/silenttiger/archive/2013/06/19/3143785.html

欢迎关注我的微信公众号:老虎的小窝

requestAnimationFrame优势何在?的更多相关文章

  1. PostgreSQL 与 MySQL 相比,优势何在?【转】

    最近看到PostgreSQL话题比较多,就搜索了一下它与mysql的对比作者:知了链接:http://www.zhihu.com/question/20010554/answer/74037965来源 ...

  2. Dashboard究竟是什么,它在数据展示上的优势何在?

    ​相信很多人在做数据分析工作的时候都遇到这种情况,辛辛苦苦做出来的数据报表老板看了嫌弃不够直观.生动,客户看了嫌弃不够高大上.这个时候不妨尝试一下使用Dashboard来展示报表数据,可能有些人对Da ...

  3. PostgreSQL 与 MySQL 相比,优势何在?

    一. PostgreSQL 的稳定性极强, Innodb 等引擎在崩溃.断电之类的灾难场景下抗打击能力有了长足进步,然而很多 MySQL 用户都遇到过Server级的数据库丢失的场景——mysql系统 ...

  4. requestAnimationFrame小结

    背景 在Web应用中,实现动画效果的方法比较多,Javascript 中可以通过定时器 setTimeout或者setInterval 来实现,css3 可以使用 transition 和 anima ...

  5. 【开源】OSharp框架解说系列(4):架构分层及IoC

    OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ...

  6. 2015-01-16 .Net 中级软件工程师 笔试题

    一 C#方面 1.请简述多线程需要考虑的主要因素 答:1.线程管理 同一核上的两个线程不会以两倍的时长完成,可能需要用两倍再加10 %左右的时间来完成.与一个线程相比较的话,三个线程在同一核上想占用1 ...

  7. 分享SQL Server 2012/2014内存数据库,AlwaysOn,参考教材与网上总结

    Sql Server 2012 高可用性的几种方案的比较,AlwaysOn优势何在 对Sql Server 2012 高可用性与灾难恢复的几种方案的比较,复制,集群,镜像优劣何在,新生技术Always ...

  8. PetShop的系统架构设计

    <解剖PetShop>系列 一.PetShop的系统架构设计 http://www.cnblogs.com/wayfarer/archive/2007/03/23/375382.html ...

  9. Java基础之泛型——使用泛型链表类型(TryGenericLinkedList)

    控制台程序 定义Point类: public class Point { // Create a point from its coordinates public Point(double xVal ...

随机推荐

  1. 安装mysql中遇到的问题1

    我的debian7之前安装了mysql-server,是通过apt安装的,后来我卸载掉, 然后用whereis mysql查找, 把所有关于mysql的目录删除掉,包括带mysqld的目录及文件. 重 ...

  2. 4027. [HEOI2015]兔子与樱花【树形DP】

    Description 很久很久之前,森林里住着一群兔子.有一天,兔子们突然决定要去看樱花.兔子们所在森林里的樱花树很特殊.樱花树由n个树枝分叉点组成,编号从0到n-1,这n个分叉点由n-1个树枝连接 ...

  3. bitMap算法实现以及ckHash函数类,将字符串映射成数字,同时可以将数字映射成字符串

    ckHash函数类,将字符串映射成数字,同时可以将数字映射成字符串 说明 1.所谓的BitMap就是用一个bit位来标记某个元素所对应的value,而key即是该元素,由于BitMap使用了bit位来 ...

  4. openfalcon-0.2 配置

    hbs 配置文件 { "debug": true, "database": "openfalcon:123456@tcp(172.16.230.188 ...

  5. Python自动化之clean方法前端调用clean方法的错误

    obj.non_field_errors.0 源代码: NON_FIELD_ERRORS = '__all__' 如果在前端写 obj.errors.__all__.0直接就会报错 所以经过尝试得知, ...

  6. MySQL插入emoji表情失败问题的解决方法

    前言 之前一直认为UTF-8是万能的字符集问题解决方案,直到最近遇到这个问题.最近在做新浪微博的爬虫, 在存库的时候发现只要保持emoji表情,就回抛出以下异常: Incorrect string v ...

  7. Python 日志输出

    昨天的任务是需要记录各操作的性能数据,所以需要用这种格式来输出日志:{"adb_start_time": 1480040663, "tag_name": &qu ...

  8. webStorm常用设置之过滤文件夹

    webStorm是一款很好用的前端IDE,但是不能否认的是webStorm很重,没有sublime轻便 尤其是项目cnpm后,加载node_modules时的状态,简直想那块豆腐自杀有莫有,就算你耐心 ...

  9. 在ubuntu中添加widows启动项的简单方法

    打开终端执行: sudo vim /boot/grub/grub.cfg 或者 sudo gedit /boot/grub/grub.cfg 打开文件grub.cfg. 在文件中添加:添加的时候注意和 ...

  10. VRRP虚IP漂移

    简介 VRRP 是 Virtual Router Redundancy Protocol 的简称,即 虚拟路由冗余协议 . 原文地址:https://linux-network-programming ...