大概半年前,无意中在网上看到一个新的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. 一、JavaScript概述 二、JavaScript的语法 三、JavaScript的内置对象

    一.JavaScript的概述###<1>JavaScript的概念 又称ECMAScript,和java没有任何关系 嵌入在HTML元素中的 被浏览器解释运行的 一种脚本语言. ###& ...

  2. 2018 徐州赛区网赛 G. Trace

    题目链接在这里 题意是:按时间先后有许多左下角固定为(0,0),右上角为(xi,yi)的矩形浪潮,每次浪潮会留下痕迹,但是后来的浪潮又会冲刷掉自己区域的老痕,留下新痕迹,问最后留下的痕迹长度为多少? ...

  3. MySQL知识总结(三)存储过程

    1. 创建存储过程 1.1 无参数存储过程 CREATE PROCEDURE bruce_procedure () BEGIN --1.声明变量 --2.执行业务逻辑 END 1.2 有参数的存储过程 ...

  4. ajax跨域请求在IE8中存在的问题

    从没打算怎么去兼容老版本IE,毕竟微软自己都放弃了,可是最近做好的东西在所有的IE下都会出问题:GetJson不执行 本来觉得挺简单的,度娘也给出了一大堆的解决方案,可惜,基本上都是在说缓存,实际上并 ...

  5. Spring 读取配置文件的俩种方式

    读取配置可通过 org.springframework.core.env.Environment 类来获取, 也可以通过@Value的方式来获取 注解形式: @PropertySource({&quo ...

  6. IDEA 使用技巧 Update

    IDEA使用起来和Eclipse很大区别. 1.快捷键. 因为一个个熟悉起来费时间,就直接在Preferences—keymap里选择了Eclipse OS X,这样快捷键就转换到了Mac下Eclip ...

  7. 2049. [SDOI2008]Cave 洞穴勘测【LCT】

    Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好 ...

  8. 20145203盖泽双 《Java程序设计》第十周学习总结

    20145203盖泽双 <Java程序设计>第十周学习总结 教材学习内容总结 一.网络概述 1.网络编程就是两个或多个设备(程序)之间的数据交换. 2.识别网络上的每个设备:①IP地址②域 ...

  9. 初识Qt文字绘制

    1.新建一个Qt Gui应用,项目名称为myDraw,基类选择为QMainWindow,类名设置为MainWindow. 2.在mainwindow.h头文件中添加void paintEvent(QP ...

  10. mapent

    package test12; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import ja ...