requestAnimationFrame,Web中写动画的另一种选择

news/2024/7/6 0:27:55 标签: javascript

HTML5/CSS3时代,我们要在web里做动画选择其实已经很多了:

你可以用CSS3的animattion+keyframes;

你也可以用css3的transition;

你还可以用通过在canvas上作图来实现动画,也可以借助jQuery动画相关的API方便地实现;

当然最原始的你还可以使用window.setTimout()或者window.setInterval()通过不断更新元素的状态位置等来实现动画,前提是画面的更新频率要达到每秒60次才能让肉眼看到流畅的动画效果。

现在又多了一种实现动画的方案,那就是还在草案当中的window.requestAnimationFrame()方法。

初识requestAnimationFrame

来看MDN上对其给出的诠释:

The window.requestAnimationFrame() method tells the browser that you wish to perform an animation and requests that the browser call a specified function to update an animation before the next repaint. The method takes as an argument a callback to be invoked before the repaint.

window.requestAnimationFrame() 将告知浏览器你马上要开始动画效果了,后者需要在下次动画前调用相应方法来更新画面。这个方法就是传递给window.requestAnimationFrame()的回调函数。

也可这个方法原理其实也就跟setTimeout/setInterval差不多,通过递归调用同一方法来不断更新画面以达到动起来的效果,但它优于setTimeout/setInterval的地方在于它是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销。

基本语法

可以直接调用,也可以通过window来调用,接收一个函数作为回调,返回一个ID值,通过把这个ID值传给window.cancelAnimationFrame()可以取消该次动画。

requestAnimationFrame(callback)//callback为回调函数

 

一个简单的例子

模拟一个进度条动画,初始div宽度为1px,在step函数中将进度加1然后再更新到div宽度上,在进度达到100之前,一直重复这一过程。

为了演示方便加了一个运行按钮(看不到例子请刷新)。

<div id="test" style="width:1px;height:17px;background:#0f0;">0%</div>
<input type="button" value="Run" id="run"/>
复制代码
window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
var start = null;
var ele = document.getElementById("test");
var progress = 0;

function step(timestamp) {
    progress += 1;
    ele.style.width = progress + "%";
    ele.innerHTML=progress + "%";
    if (progress < 100) {
        requestAnimationFrame(step);
    }
}
requestAnimationFrame(step);
document.getElementById("run").addEventListener("click", function() {
    ele.style.width = "1px";
    progress = 0;
    requestAnimationFrame(step);
}, false);
复制代码

 

浏览器支持情况

既然还是草案状态下引入的一个功能,在使用全我们就需要关心一下各浏览器对它的支持情况了。就目前来说,主流现代浏览器都对它提供了支持,请看下图:

31+

26+

10+

19+

6+

 

更为具体的浏览器兼容性可以在这里看到。

Polyfill

Polyfill就是垫片,按发明这个词的人的原话来说,它就是一段这样的代码,让浏览器原生地支持我们期望使用的一些API。

就比如这里的requestAnimationFrame,在看到了上面的浏览器支持情况后,你就知道了比上面列出的浏览器版本老的就不支持该方法,但为了让代码能够有更好的浏览器兼容性在老机器上也能运行不报错,我们可以写一些代码让浏览器在不支持requestAnimationFrame的情况下使用window.setTimeout(),这是一种回退(fallback)到过去的方法。

这样一来,就可以通俗一点的理解polyfill了,它就是备胎。

下面是由Paul Irish及其他贡献者放在GitHub Gist上的代码片段,用于在浏览器不支持requestAnimationFrame情况下的回退,回退到使用setTmeout的情况。当然,如果你确定代码是工作在现代浏览器中,下面的代码是不必的。

复制代码
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
// MIT license
(function() {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    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);
    };
}());
复制代码

 

上面代码作用有二,一是把各浏览器前缀进行统一,二是在浏览器没有requestAnimationFrame方法时将其指向setTimeout方法。

提到备胎代码呢,这里多说一句,在CSS代码中,我们也经常使用这种回退的技巧,即对同一条CSS规则,编写多条以不同浏览器前缀开头代码,或者编写一条备用样式。

下面是一个CSS中的备胎代码的例子:

div {
    background: rgb(0, 0, 0); /* fallback */
    background: rgba(0, 0, 0, 0.5);
}

 

代码中设置div背景为黑色带50%的透明度,但IE9-的浏览器是不支持rbga格式的颜色的,所以浏览器会回退到上一条CSS规则应用rgb颜色。

 


http://www.niftyadmin.cn/n/1339334.html

相关文章

C++ 、、 |、|| 、|=、?: 逻辑运算符用法

C &、&& |、|| 与|逻辑运算符用法&与&&|与|||?:参考链接&与&& &&     表示逻辑与的意思&#xff0c;即为and。当运算符两边的表达式的结果都为true时&#xff0c;整个运算结果才为true&#xff0c;否则&#xff0c;只要有一…

麦进斗:magento如何安装子主题

让我们的孩子创造一个主题&#xff0c;我们所有的自定义主题在Magento 2去这里&#xff1a;应用程序/设计/开发/ company_name / theme_name让我们假设&#xff0c;我们公司的名称是公司和我们的主题名称是基本。我们需要创建以下主题目录结构&#xff1a;<app><desig…

C++ Vector容器的push_back( )与pop_back( )函数

C Vector容器的push_back&#xff08;&#xff09;与pop_back&#xff08;&#xff09;函数push_back( )pop_back( )参考链接push_back( ) 函数将一个新的元素加到vector的最后面&#xff0c;位置为当前最后一个元素的下一个元素 push_back() 在Vector最后添加一个元素&#x…

高性能、高流量Java Web站点打造的22条建议

http://www.csdn.net/article/2013-12-20/2817861-22-recommendations-for-building-effective-high-traffic-web-application/2从2005年-2013年&#xff0c;Ashwanth Fernando曾供职于Best Buy、Pearson VUE、Walgreens、Walmart eCommerce等多家知名公司&#xff0c;现在Appl…

Nvidia Video Codec SDK——AppDec解析

Nvidia Video Codec SDK——AppDec解析项目框架AppDec硬解码整体框架主函数main具体硬解码流程函数DecodeMediaFile初始化解码器实际解码函数Decode回调函数HandlePictureDisplay数据指针参考链接项目框架 使用的SDK版本是Video_Codec_SDK_8.2.16&#xff0c;下载链接&#xf…

JAVACARD减少应用开发风险的建议

参考Java Card & STK Applet Development Guidelines by gemalto文档。 由于EEPROM和闪存的寿命有限&#xff0c;应用频繁的读写同一位置可能导致运行故障。本文主要描述了如何设计程序&#xff0c;尽量最小读写内存的必要。如果不遵守本文的建议的话&#xff0c;实际运行过…

CUDA高性能并行计算学习笔记1----认识CUDA

CUDA高性能并行计算学习笔记1----认识CUDACUDA C基础函数类型限定符执行配置运算符五个内置变量变量类型限定符转载链接CUDA C基础 CUDA C是对C/C语言进行拓展后形成的变种&#xff0c;兼容C/C语法&#xff0c;文件类型为”.cu”文件&#xff0c;编译器为”nvcc”&#xff0c;…

解决32位plsql客户端连接不64位Oracle11g上数据库

一、解决方案 因为本人安装的是64位的Oracle&#xff0c;plsql 是32位的故连接不上。网上有方法能连接。 1. 文件下载 下载PLSQL_Developer地址 http://pan.baidu.com/share/link?shareid3768883331&uk3557941237 下载instantclient-basic-win32-10.2.0.5地址&#xff1a;…