BOM系列第二篇之定时器requestAnimationFrame


Posted in Javascript onAugust 17, 2016

引入

计时器一直是javascript动画的核心技术。而编写动画循环的关键是要知道延迟时间多长合适。一方面,循环间隔必须足够短,这样才能让不同的动画效果显得平滑流畅;另一方面,循环间隔还要足够长,这样才能确保浏览器有能力渲染产生的变化

大多数电脑显示器的刷新频率是60Hz,大概相当于每秒钟重绘60次。大多数浏览器都会对重绘操作加以限制,不超过显示器的重绘频率,因为即使超过那个频率用户体验也不会有提升。因此,最平滑动画的最佳循环间隔是lOOOms/60,约等于16.6ms

而setTimeout和setInterval的问题是,它们都不精确。它们的内在运行机制决定了时间间隔参数实际上只是指定了把动画代码添加到浏览器UI线程队列中以等待执行的时间。如果队列前面已经加入了其他任务,那动画代码就要等前面的任务完成后再执行

requestAnimationFrame采用系统时间间隔,保持最佳绘制效率,不会因为间隔时间过短,造成过度绘制,增加开销;也不会因为间隔时间太长,使用动画卡顿不流畅,让各种网页动画效果能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果

特点

【1】requestAnimationFrame会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率

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

【3】requestAnimationFrame是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销

使用

requestAnimationFrame的用法与settimeout很相似,只是不需要设置时间间隔而已。requestAnimationFrame使用一个回调函数作为参数,这个回调函数会在浏览器重绘之前调用。它返回一个整数,表示定时器的编号,这个值可以传递给cancelAnimationFrame用于取消这个函数的执行

requestID = requestAnimationFrame(callback); 
//控制台输出1和0
var timer = requestAnimationFrame(function(){
console.log(0);
}); 
console.log(timer);//1 
cancelAnimationFrame方法用于取消定时器
//控制台什么都不输出
var timer = requestAnimationFrame(function(){
console.log(0);
}); 
cancelAnimationFrame(timer);

也可以直接使用返回值进行取消

var timer = requestAnimationFrame(function(){
console.log(0);
}); 
cancelAnimationFrame(1);

兼容

IE9-浏览器不支持该方法,可以使用setTimeout来兼容

if(!window.requestAnimationFrame){
var lastTime = 0;
window.requestAnimationFrame = function(callback){
var currTime = new Date().getTime();
var timeToCall = Math.max(0,16.7-(currTime - lastTime));
var id = window.setTimeout(function(){
callback(currTime + timeToCall);
},timeToCall);
lastTime = currTime + timeToCall;
return id;
}
} 
if (!window.cancelAnimationFrame) {
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
}

应用

现在分别使用setInterval、setTimeout和requestAnimationFrame这三个方法制作一个简单的进制度效果

【1】setInterval

<div id="myDiv" style="background-color: lightblue;width: 0;height: 20px;line-height: 20px;">0%</div>
<button id="btn">run</button>
<script>
var timer;
btn.onclick = function(){
clearInterval(timer);
myDiv.style.width = '0';
timer = setInterval(function(){
if(parseInt(myDiv.style.width) < 500){
myDiv.style.width = parseInt(myDiv.style.width) + 5 + 'px';
myDiv.innerHTML = parseInt(myDiv.style.width)/5 + '%'; 
}else{
clearInterval(timer);
} 
},16);
}
</script>

BOM系列第二篇之定时器requestAnimationFrame

【2】setTimeout

<div id="myDiv" style="background-color: lightblue;width: 0;height: 20px;line-height: 20px;">0%</div>
<button id="btn">run</button>
<script>
var timer;
btn.onclick = function(){
clearTimeout(timer);
myDiv.style.width = '0';
timer = setTimeout(function fn(){
if(parseInt(myDiv.style.width) < 500){
myDiv.style.width = parseInt(myDiv.style.width) + 5 + 'px';
myDiv.innerHTML = parseInt(myDiv.style.width)/5 + '%';
timer = setTimeout(fn,16);
}else{
clearTimeout(timer);
} 
},16);
}
</script>

BOM系列第二篇之定时器requestAnimationFrame

【3】requestAnimationFrame

<div id="myDiv" style="background-color: lightblue;width: 0;height: 20px;line-height: 20px;">0%</div>
<button id="btn">run</button>
<script>
var timer;
btn.onclick = function(){
myDiv.style.width = '0';
cancelAnimationFrame(timer);
timer = requestAnimationFrame(function fn(){
if(parseInt(myDiv.style.width) < 500){
myDiv.style.width = parseInt(myDiv.style.width) + 5 + 'px';
myDiv.innerHTML = parseInt(myDiv.style.width)/5 + '%';
timer = requestAnimationFrame(fn);
}else{
cancelAnimationFrame(timer);
} 
});
}
</script>

BOM系列第二篇之定时器requestAnimationFrame

好了,代码到此介绍,下面给大家介绍BOM系列第三篇之定时器应用(时钟、倒计时、秒表和闹钟)

以上所述是小编给大家介绍的BOM系列第二篇之定时器requestAnimationFrame ,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
extjs中grid中嵌入动态combobox的应用
Jan 01 Javascript
jquery 插件学习(二)
Aug 06 Javascript
基于JQuery的一句话搞定手风琴菜单
Sep 14 Javascript
基于JQuery 滑动与动画的说明介绍
Apr 18 Javascript
JavaScript动态插入script的基本思路及实现函数
Nov 11 Javascript
常用的JQuery函数及功能小结
Mar 24 Javascript
微信小程序 自定义对话框实例详解
Jan 20 Javascript
前端必备插件之纯原生JS的瀑布流插件Macy.js
Nov 22 Javascript
vue-自定义组件传值的实例讲解
Sep 18 Javascript
el-select 下拉框多选实现全选的实现
Aug 02 Javascript
no-vnc和node.js实现web远程桌面的完整步骤
Aug 11 Javascript
ESLint 是如何检查 .vue 文件的
Nov 30 Vue.js
AngularJS 视图详解及示例代码
Aug 17 #Javascript
BOM系列第三篇之定时器应用(时钟、倒计时、秒表和闹钟)
Aug 17 #Javascript
AngularJS Ajax详解及示例代码
Aug 17 #Javascript
AngularJS包括详解及示例代码
Aug 17 #Javascript
详细分析Javascript中创建对象的四种方式
Aug 17 #Javascript
AngularJS表单详解及示例代码
Aug 17 #Javascript
AngularJS模块详解及示例代码
Aug 17 #Javascript
You might like
如何在Ubuntu下启动Apache的Rewrite功能
2013/07/05 PHP
PHP二维数组去重实例分析
2016/11/18 PHP
对php 判断http还是https,以及获得当前url的方法详解
2019/01/15 PHP
为javascript添加String.Format方法
2020/08/11 Javascript
基于jquery实现的定时显示与隐藏div广告的实现代码
2013/08/22 Javascript
查询json的数据结构的8种方式简介
2014/03/10 Javascript
node.js Web应用框架Express入门指南
2014/05/28 Javascript
JavaScript实现向OL列表内动态添加LI元素的方法
2015/03/21 Javascript
nodejs开发微博实例
2015/03/25 NodeJs
jQuery的事件委托实例分析
2015/07/15 Javascript
jquery中实现时间戳与日期相互转换
2016/04/12 Javascript
SWFUpload多文件上传及文件个数限制的方法
2016/05/31 Javascript
AngularJS轻松实现双击排序的功能
2016/08/30 Javascript
jQuery插件echarts实现的循环生成图效果示例【附demo源码下载】
2017/03/04 Javascript
angular 基于ng-messages的表单验证实例
2017/05/04 Javascript
JavaScript与Java正则表达式写法的区别介绍
2017/08/15 Javascript
VSCode写vue项目一键生成.vue模版,修改定义其他模板的方法
2020/04/17 Javascript
解决Nuxt使用axios跨域问题
2020/07/06 Javascript
[59:48]DOTA2-DPC中国联赛 正赛 VG vs Magma BO3 第一场 1月26日
2021/03/11 DOTA
详解Python实现按任意键继续/退出的功能
2016/08/19 Python
PyQt5打开文件对话框QFileDialog实例代码
2018/02/07 Python
Pyinstaller打包.py生成.exe的方法和报错总结
2019/04/02 Python
用vue.js组件模拟v-model指令实例方法
2019/07/05 Python
Python数据可视化处理库PyEcharts柱状图,饼图,线性图,词云图常用实例详解
2020/02/10 Python
Python如何实现在字符串里嵌入双引号或者单引号
2020/03/02 Python
吉尔德利巧克力公司:Ghirardelli Chocolate Company
2019/03/27 全球购物
如何启动时不需输入用户名与密码
2014/05/09 面试题
Java面试题:说出如下代码的执行结果
2015/10/30 面试题
大学生应聘自荐信
2013/10/11 职场文书
主管职责范文
2013/11/09 职场文书
化学教师教学反思
2014/01/17 职场文书
大学校园活动策划书
2014/02/04 职场文书
写给父母的感谢信
2015/01/22 职场文书
如何用python绘制雷达图
2021/04/24 Python
python3实现常见的排序算法(示例代码)
2021/07/04 Python