canvas雨滴绘制之(四)requestAnimationFrame
来源:互联网 发布:制冷系统仿真软件 编辑:程序博客网 时间:2024/04/29 16:57
canvas雨滴绘制程序:canvas雨滴特效
参考文献1:HTML5探秘:用requestAnimationFrame优化Web动画
参考文献2:使用requestAnimationFrame()优化JavaScript动画性能
参考文献3:CSS3动画那么强,requestAnimationFrame还有毛线用
canva绘制雨滴程序中:requestAnimationFrame(move);
CDN定义:: 此方法告诉浏览器您希望执行动画,并请求浏览器调用指定的函数在下一次重绘之前更新动画。该方法使用一个回调函数作为参数,这个回调函数会在浏览器重绘之前调用。
requestAnimationFrame是什么?
在浏览器动画程序中,我们通常使用一个定时器来循环每隔几毫秒移动目标物体一次,来让它动起来。如今有一个好消息,浏览器开发商们决定:“嗨,为什么我们不在浏览器里提供这样一个API呢,这样一来我们可以为用户优化他们的动画。”
所以,这个requestAnimationFrame()函数就是针对动画效果的API,你可以把它用在DOM上的风格变化或画布动画或WebGL中。
进一步理解
在JavaScript里曾经只有一种方法来设定定时循环任务:setInterval()。如果你想快速的重复有些动作(但又不是像直接调用for循环那样立即执行),你就需要用到定时调度。最常见的就是动画绘制过程,当动画的绘制速度达到每秒钟60帧时,动画会显得非常的流畅。
于是,你需要允许像下面这样一个定时循环任务:
setInterval(function() { // 做某些动画任务}, 1000/60);
但现在有了一个新的、性能更好的方法可以实现这个任务。requestAnimationFrame()方法。
原理:
相当一部分的浏览器的显示频率是16.7ms,当显示器16.7ms刷新间隔之前发生了其他绘制请求(setTimeout),例如搞个10ms setTimeout,强行要10s显示。显然,这是超负荷的,要想顺利进行,只能让一些帧消失。然而,这是不现实的,于是就有了卡顿,动画断续显示,这就是过度绘制带来的问题。
不仅如此,这种计时器频率的降低也会对电池使用寿命造成负面影响,并会降低其他应用的性能。
这也是为何setTimeout的定时器值推荐最小使用16.7ms的原因(16.7 = 1000 / 60, 即每秒60帧)。
requestAnimationFrame发生了什么?
requestAnimationFrame所做的事情很简单,跟着浏览器的绘制走,如果浏览设备绘制间隔是16.7ms,那我就这个间隔绘制;如果浏览设备绘制间隔是10ms, 我就10ms绘制。这样就不会存在过度绘制的问题,动画不会掉帧,自然流畅~~
内部是这么运作的:
浏览器(如页面)每次要重绘,就会通知(requestAnimationFrame):可以渲染了!
这是资源非常高效的一种利用方式。怎么讲呢?
- 就算很多个rAF要一起渲染,浏览器只要通知一次就可以了。而setTimeout貌似是多个独立绘制。
- 页面最小化了,或者被Tab切换关灯了。页面是不会render的,自然,rAF也不会render的(没通知)。页面绘制全部停止,资源高效利用。
总结:
为什么requestAnimationFrame()更好?
浏览器可以优化并行的动画动作,更合理的重新排列动作序列,并把能够合并的动作放在一个渲染周期内完成,从而呈现出更流畅的动画效果。比如,通过requestAnimationFrame(),JS动画能够和CSS动画/变换或SVG SMIL动画同步发生。
在一个浏览器标签页里运行一个动画,当这个标签页不可见时,浏览器会暂停它,这会减少CPU,内存的压力,节省电池电量。
最简单的一个使用requestAnimationFrame()的例子
function repeatOften() { // 做某些事情 requestAnimationFrame(repeatOften);}requestAnimationFrame(repeatOften);
这个方法一旦启动,它就会递归的调用自己。
requestAnimationFrame的用法:封装
// shim layer with setTimeout fallbackwindow.requestAnimFrame = (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function( callback ){ window.setTimeout(callback, 1000 / 60); };})();// usage:// instead of setInterval(render, 16) ....(function animloop(){ requestAnimFrame(animloop); render();})();// place the rAF *before* the render() to assure as close to// 60fps with the setTimeout fallback.
启动和停止
requestAnim
ationFrame 函数能返回一个ID,根据这个ID,你可以停止它的允许,这就像 setTimeout 和 setInterval 的用法一样。下面是一个实际可运行的例子:
var globalID;function repeatOften() { document.getElementsByTagName("body").appendChild('#');; globalID = requestAnimationFrame(repeatOften);}$("#start").on("click", function() { globalID = requestAnimationFrame(repeatOften);});$("#stop").on("click", function() { cancelAnimationFrame(globalID);});
运行效果
对requestAnimationFrame更牢靠的封装
但是呢,并不是所有设备的绘制时间间隔是1000/60 ms, 以及上面并木有cancel相关方法,所以,就有下面这份更全面的兼容方法:
Opera浏览器的技术师Erik Möller 把这个函数进行了封装,使得它能更好的兼容各种浏览器。你可以读一读这篇文章,但基本上他的代码就是判断使用4ms还是16ms的延迟,来最佳匹配60fps。下面就是这段代码,你可以使用它,但请注意,这段代码里使用的是标准函数,我给它加上了兼容各种浏览器引擎前缀。
(function() { var lastTime = 0; var vendors = ['webkit', 'moz']; for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame']; } if (!window.requestAnimationFrame) window.requestAnimationFrame = function(callback, element) { var currTime = new Date().getTime(); var timeToCall = Math.max(0, 16 - (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); };}());
然后,我们就可以以使用setTimeout的调调使用requestAnimationFrame方法啦,IE6也能支持哦!
各种浏览器对requestAnimationFrame的支持情况
谷歌浏览器,火狐浏览器,IE10+都实现了这个函数,即使你的浏览器很古老,上面的对requestAnimationFrame封装也能让这个方法在IE8/9上不出错。2017-12-11:rAF的兼容性性
There’s an issue with requestAnimationFrame on iOS6, the bug still appears to exist in 6.1.3
- canvas雨滴绘制之(四)requestAnimationFrame
- Canvas绘制雨滴(二)之setInterval与setTimeout
- canvas雨滴绘制总结(三)
- 案例-雨滴-canvas绘制
- Canvas绘制雨滴之setInterval与setTimeout(一)
- canvas雨滴绘制(五)最终实现代码
- canvas requestAnimationFrame
- canvas实现雨滴效果
- canvas 雨滴demo
- 图形绘制之——Canvas详解(四)-Bitmap(位图)及Matrix矩阵
- 详述Canvas(四)/绘制曲线
- 详述Canvas(四)/绘制曲线
- window.requestAnimationFrame(drawFrame, canvas)
- canvas动画函数requestAnimationFrame
- Android绘制之Canvas
- Canvas之绘制字符串
- html5之canvas绘制
- requestAnimationFrame绘制图像
- 【Unity内存】从认识到优化
- C# CAD视图操作之缩放
- Retrofit 2.0 注解分类详解
- win10-vs2015编译cef3.2023
- 使用axis2,根据WSDL生成java客户端代码
- canvas雨滴绘制之(四)requestAnimationFrame
- 数据结构实验之排序一:一趟快排
- hibernate之表关系中的一对多
- 1.Two Sum
- 使用CountDownTimer实现倒计时功能
- android as呼起APP协议
- 高数 07.11 多元函数微分学习题03B二重积分
- mysql几个‘冷语句’笔记
- Spring创建bean