Internet Explorer 10 和使用 JavaScript 的 Windows 应用商店应用引入了对requestAnimationFrame 方法的支持,该方法通过在系统准备好绘制动画帧时调用该帧,从而为创建动画网页提供了一种更平滑更高效的方法。在此 API 之前,使用 setTimeout 和 setInterval 绘制的动画并没有为 Web 开发人员提供有效的方法来规划动画的图形计时器。这导致了动画过度绘制,浪费 CPU 周期以及消耗额外的电能等问题。而且,即使看不到网站,特别是当网站使用背景选项卡中的页面或浏览器已最小化时,动画都会频繁出现。
当动画使用分辨率为 10ms 的 JavaScript 计时器绘制动画时,计时可能不匹配,如下所示。
上面一行表示大多数监视器上显示的 16.7ms 显示频率,而下面一行表示通常的 10ms setTimeout。每个第三个图形都无法绘制(由红色箭头指示),因为在显示器刷新间隔之前发生了其他绘制请求。这种过度绘制的情况会导致动画断续显示,因为所有第三帧都会丢失。这种计时器分辨率的降低也会对电池使用寿命造成负面影响,并会降低其他应用的性能。
requestAnimationFrame 方法(在万维网联合会 (W3C) 的针对基于脚本的动画的计时控制规范中定义)可以解决丢失帧的问题,因为它使应用能够在浏览器需要更新页面显示时(而且仅在这种情况下)获得通知。 因此,应用可与浏览器的绘制时间间隔保持完全一致,并且仅使用适量的资源。从 setTimeout 切换到 requestAnimationFrame 非常容易,因为它们都规划单个回调。要实现持续的动画,请在调用动画函数后再次调用 requestAnimationFrame。
使用 requestAnimationFrame
要使用这个新的 API,只需使用回调函数调用 requestAnimationFrame 即可。计时由系统处理。 如果当前使用setTimeout 来驱动动画计时,如下所示:
var handle = setTimeout(renderLoop, PERIOD);
你可以将 setTimeout 替换为 requestAnimationFrame,如下所示:
var handle = requestAnimationFrame(renderLoop);
这会影响你的第一个重画。若要保持动画继续运行,则需要从回调函数(如此处的 renderLoop)中再次调用requestAnimationFrame。
<!DOCTYPE html> <html> <head> <title>Script-based animation using requestAnimationFrame</title> <style type="text/css"> #animated { position: absolute; top:100px; padding: 50px; background: crimson; color: white; } </style> </head> <body> <div>Click the box to stop it</div> <div id="animated">Hello there.</div> <script type="text/javascript"> // global variables var elm = document.getElementById("animated"); var handle = 0; var lPos = 0; renderLoop(Date.now); // call animation frame to start function renderLoop(time) { elm.style.left = ((lPos += 3) % 600) + "px"; handle = window.requestAnimationFrame(renderLoop); } // click the box to stop the animation document.getElementById("animated").addEventListener("click", function () { if (handle) { window.cancelAnimationFrame(handle); } }, false); </script> </body> </html>
本示例使用 getElementById 将 <div> 元素保存到一个全局变量。调用 renderLoop() 函数以开始动画。在重新定位 <div> 元素后,再次调用 requestAnimationFrame 以设置下一次移动。此操作将继续执行,直至你关闭浏览器或单击 <div> 元素为止。
addEventListener 方法处理 <div> 元素上的单击事件。当你单击该元素时,将使用当前句柄调用cancelAnimationFrame。
回调函数中的时间
你可以使用回调函数对几乎所有内容(如 SVG、Canvas 或此处所示的 CSS 属性)设置动画。回调函数具有一个传入time 参数,该参数表示调用回调函数的时间。它是一个 DOMHighResTimeStamp,是从页面导航开始时测量的高精确度时间。DOMHighResTimeStamp 以毫秒为单位,精确到千分之一毫秒。此时间值不直接与 Date.now() 进行比较,后者测量自 1970 年 1 月 1 日至今以毫秒为单位的时间。如果你希望将 time 参数与当前时间进行比较,请使用当前时间的window.performance.now。将时间值从 DOMTimeStamp 更改为 DOMHighResTimeStamp 是 W3C 针对基于脚本动画计时控制规范的最新编辑草案中的最新更改,并且某些供应商仍将其作为 DOMTimeStamp 实现。较早版本的 W3C 规范使用 DOMTimeStamp,允许你将 Date.now 用于当前时间。
浏览器支持
如上所述,某些浏览器供应商可能仍实现 DOMTimeStamp 参数,或者尚未实现 window.performance.now 计时函数。由于 W3C 规范尚未最后定稿,因此其他浏览器制造商已创建其自己的 requestAnimationFrame 和cancelAnimationFrame 前缀实现。本例提供了一个我们的动画程序版本,该程序使用 Time 移动 <div> 元素并在多个浏览器上使用。
<!DOCTYPE html> <html> <head> <title>Script-based animation using requestAnimationFrame</title> <style type="text/css"> div { position: absolute; left: 10px; top:100px; padding: 50px; background: crimson; color: white } </style> <script type="text/javascript"> var requestId = 0; var startime = 0; var elm; function init() { elm = document.getElementById("animated"); } function render(time) { elm.style.left = ((time - startime) / 4 % 600) + "px"; requestId = window.requestAFrame(render); } function start() { if (window.performance.now) { startime = window.performance.now(); } else { startime = Date.now(); } requestId = window.requestAFrame(render);s } function stop() { if (requestId) window.cancelAFrame(requestId); } // handle multiple browsers for requestAnimationFrame() window.requestAFrame = (function () { return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || // if all else fails, use setTimeout function (callback) { return window.setTimeout(callback, 1000 / 60); // shoot for 60 fps }; })(); // handle multiple browsers for cancelAnimationFrame() window.cancelAFrame = (function () { return window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.oCancelAnimationFrame || function (id) { window.clearTimeout(id); }; })(); </script> </head> <body onload="init();"> <div id="animated">Hello there.</div> <button onclick="start()">Start</button> <button onclick="stop()">Stop</button> </body> </html>
本例是 W3C 规范的一个扩展示例,添加了供应商前缀元素。此外,本例还对 window.performance.now 进行测试,如果不支持此函数,则使用 Date.now 获取当前时间。
API 参考
示例和教程
有关 Internet Explorer 的 Test Drive 演示
规范
http://msdn.microsoft.com/zh-cn/library/ie/hh920765(v=vs.85).aspx#multiplebrowsers
相关链接:http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
相关推荐
Unity3d脚本控制动画(开关门)代码
基于TIA博途的触摸屏HMI脚本入门学习(四)使用脚本控制按钮的使能开关
unity3d UV动画脚本,可以调节贴图的UV动画 X Y 的移动和速度都可以调整
使用脚本控制Unity场景内的模型播放动画
倒计时页面特效脚本
倒计时脚本程序javascript,简单易用方便整合到页面中!
一个基于时间帧的动画 通过脚本控制时间帧的播放
关于动画的flash脚本教程,对于flash感兴趣的刚入门的人可以看看
基于python脚本ocv图片转换,dlib库定位五官位置基于python脚本ocv图片转换,dlib库定位五官位置基于python脚本ocv图片转换,dlib库定位五官位置基于python脚本ocv图片转换,dlib库定位五官位置基于python脚本ocv...
老鹰MG动画脚本
动画分镜头脚本课.pdf
脚本和脚本动画PPT学习教案.pptx
Flash脚本控制实现倒计时的效果,可以添加在网页中的效果
奥运倒计时java脚本.txt文本格式.
基于脚本和testbench的NCVERILOG仿真
倒计时脚本代码
c 语言模式脚本解析器,脚本执行不是其目的。其作用是对PE文件进行编辑。暂且不论。 现在仅支持 if关键字、以及一些+-/* && || 等常规操作。 操作符支持优先级,但不支持括号。 今天调试成功,先放出来,让大家看看...
unity 键鼠控制摄像机移动 脚本 鼠标右键控制镜头 WASD控制前后左右移动 空格向上移动 Ctrl向下移动 按住shift加速 脚本特点是:摄像机被Dotween或其它方法移动过后 用此脚本再次控制摄像机不会出现画面跳转的问题
脚本动画的制作.doc
js计时器,功能有:开始计时,暂停计时器,停止计时器