requestAnimationFrame优势何在?
大概半年前,无意中在网上看到一个新的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优势何在?的更多相关文章
- PostgreSQL 与 MySQL 相比,优势何在?【转】
最近看到PostgreSQL话题比较多,就搜索了一下它与mysql的对比作者:知了链接:http://www.zhihu.com/question/20010554/answer/74037965来源 ...
- Dashboard究竟是什么,它在数据展示上的优势何在?
相信很多人在做数据分析工作的时候都遇到这种情况,辛辛苦苦做出来的数据报表老板看了嫌弃不够直观.生动,客户看了嫌弃不够高大上.这个时候不妨尝试一下使用Dashboard来展示报表数据,可能有些人对Da ...
- PostgreSQL 与 MySQL 相比,优势何在?
一. PostgreSQL 的稳定性极强, Innodb 等引擎在崩溃.断电之类的灾难场景下抗打击能力有了长足进步,然而很多 MySQL 用户都遇到过Server级的数据库丢失的场景——mysql系统 ...
- requestAnimationFrame小结
背景 在Web应用中,实现动画效果的方法比较多,Javascript 中可以通过定时器 setTimeout或者setInterval 来实现,css3 可以使用 transition 和 anima ...
- 【开源】OSharp框架解说系列(4):架构分层及IoC
OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ...
- 2015-01-16 .Net 中级软件工程师 笔试题
一 C#方面 1.请简述多线程需要考虑的主要因素 答:1.线程管理 同一核上的两个线程不会以两倍的时长完成,可能需要用两倍再加10 %左右的时间来完成.与一个线程相比较的话,三个线程在同一核上想占用1 ...
- 分享SQL Server 2012/2014内存数据库,AlwaysOn,参考教材与网上总结
Sql Server 2012 高可用性的几种方案的比较,AlwaysOn优势何在 对Sql Server 2012 高可用性与灾难恢复的几种方案的比较,复制,集群,镜像优劣何在,新生技术Always ...
- PetShop的系统架构设计
<解剖PetShop>系列 一.PetShop的系统架构设计 http://www.cnblogs.com/wayfarer/archive/2007/03/23/375382.html ...
- Java基础之泛型——使用泛型链表类型(TryGenericLinkedList)
控制台程序 定义Point类: public class Point { // Create a point from its coordinates public Point(double xVal ...
随机推荐
- php常用算法和数据结构
</pre><pre name="code" class="php"><?php /** * Created by PhpStor ...
- 2018 徐州赛区网赛 G. Trace
题目链接在这里 题意是:按时间先后有许多左下角固定为(0,0),右上角为(xi,yi)的矩形浪潮,每次浪潮会留下痕迹,但是后来的浪潮又会冲刷掉自己区域的老痕,留下新痕迹,问最后留下的痕迹长度为多少? ...
- Android开发经验02:Android 项目开发流程
Android开发完整流程: 一.用户需求分析 用户需求分析占据整个APP开发流程中最重要的一个环节.一款APP开发的成功与否很大程度都决定于此.这里所说的用户需求分析指的是基于用户的要求所进行的 ...
- swift的enum基础
其它语言的枚举: 符号化的整型常量的集合: swift的枚举: 可以是任何基础类型和无类型: If you are familiar with C, you will know that C enum ...
- Day18 (一)类的加载器
一个运行时的Java虚拟机(JVM)负责运行一个Java程序. 当启动一个Java程序时,一个虚拟机实例诞生:当程序关闭退出,这个虚拟机实例也就随之消亡. 如果在同一台计算机上同时运行多个Java程序 ...
- grovvy pipeline 部署
pipeline { agent any stages { stage('Checkout') { steps { echo 'Checkout' checkout([$class: 'GitSCM' ...
- Java反射学习一
Java 反射机制 基本概念 在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法? 答案是肯定的. 这种动态获取类的信息以及动态调用对象 ...
- LeetCode872. Leaf-Similar Trees
自己的代码: # Definition for a binary tree node. # class TreeNode: # def __init__(self, x): # self.val = ...
- json2.js的作用与使用示例
工作中,如果公司要求你兼容ie6.7,那么你可以辞职了,开个玩笑: 关于json,本文不作介绍,介绍一下json字符串和对象的相互转换: 在各大主浏览器及ie8+,我们可以使用内置方法JSON.str ...
- P2280 [HNOI2003]激光炸弹
题目描述 输入输出格式 输入格式: 输入文件名为input.txt 输入文件的第一行为正整数n和正整数R,接下来的n行每行有3个正整数,分别表示 xi,yi ,vi . 输出格式: 输出文件名为out ...