zoukankan      html  css  js  c++  java
  • requestAnimationFrame/cancelAnimationFrame——性能更好的js动画实现方式

    用js来实现动画,我们一般是借助setTimeout或setInterval这两个函数,css3动画出来后,我们又可以使用css3来实现动画了,而且性能和流畅度也得到了很大的提升。但是css3动画还是有不少局限性,比如不是所有属性都能参与动画、动画缓动效果太少、无法完全控制动画过程等等。所以有的时候我们还是不得不使用setTimeout或setInterval的方式来实现动画,可是setTimeout和setInterval有着严重的性能问题,虽然某些现代浏览器对这两函个数进行了一些优化,但还是无法跟css3的动画性能相提并论。这个时候,就该requestAnimationFrame出马了。

    requestAnimationFrame 是专门为实现高性能的帧动画而设计的一个API,目前已在多个浏览器得到了支持,包括IE10+,Firefox,Chrome,Safari,Opera等,在移动设备上,ios6以上版本以及IE mobile 10以上也支持requestAnimationFrame,唯一比较遗憾的是目前安卓上的原生浏览器并不支持requestAnimationFrame,不过对requestAnimationFrame的支持应该是大势所趋了,安卓版本的chrome 16+也是支持requestAnimationFrame的。

    在这里插入图片描述


    requestAnimationFrame 比起 setTimeout、setInterval的优势主要有两点:

    1、requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。

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


    注意:

    像setTimeout、setInterval一样,requestAnimationFrame是一个全局函数。调用requestAnimationFrame后,它会要求浏览器根据自己的频率进行一次重绘,它接收一个回调函数作为参数,在即将开始的浏览器重绘时,会调用这个函数,并会给这个函数传入调用回调函数时的时间作为参数。由于requestAnimationFrame的功效只是一次性的,所以若想达到动画效果,则必须连续不断的调用requestAnimationFrame,就像我们使用setTimeout来实现动画所做的那样。requestAnimationFrame函数会返回一个资源标识符,可以把它作为参数传入cancelAnimationFrame函数来取消requestAnimationFrame的回调。怎么样,是不是也跟setTimeout的clearTimeout很相似啊。

    所以,可以这么说,requestAnimationFrame就是一个性能优化版、专为动画量身打造的setTimeout,不同的是requestAnimationFrame不是自己指定回调函数运行的时间,而是跟着浏览器内建的刷新频率来执行回调,这当然就能达到浏览器所能实现动画的最佳效果了。

    目前,各个支持requestAnimationFrame的浏览器有些还是自己的私有实现,所以必须加前缀,对于不支持requestAnimationFrame的浏览器,我们只能使用setTimeout,因为两者的使用方式几近相同,所以这两者的兼容并不难。对于支持requestAnimationFrame的浏览器,我们使用requestAnimationFrame,而不支持的我们优雅降级使用传统的setTimeout。把它们封装一下,就能得到一个统一兼容各大浏览器的API了。

    (function() {
    	var lastTime = 0;
    	var vendors = ['webkit', 'moz', 'ms', 'o'];
    	for( var x=0 ; x<vendors.length ; ++x){
    		if ( window.requestAnimationFrame && window.cancelAnimationFrame ) {
       			break;
    		}
    		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); 
    		};
    	}
    }());
    

    //简化版本

    window.requestAnimationFrame=window.requestAnimationFrame ||
    	window.webkitRequestAnimationFrame ||
    	window.mozRequestAnimationFrame ||
    	window.msRequestAnimationFrame ||
    	window.oRequestAnimationFrame ||
    	function( callback ){
    		//为了使setTimteout的尽可能的接近每秒60帧的效果
    		window.setTimeout(callback,1000/60);
    	}
     
    window.cancelAnimationFrame=window.cancelAnimationFrame ||
    	Window.webkitCancelAnimationFrame ||
    	window.mozCancelAnimationFrame ||
    	window.msCancelAnimationFrame ||
    	window.oCancelAnimationFrame ||
    	function( id ){
    		//为了使setTimteout的尽可能的接近每秒60帧的效果
    		window.clearTimeout( id );
    	}
    

    下面举个简单的例子来说明怎么运用requestAnimationFrame进行动画,下面的代码会将id为demo的div以动画的形式向右移动到300px
    <div id="demo" style="position:absolute; 100px; height:100px; background:#ccc; left:0; top:0;"></div>
    <script>
    	var demo = document.getElementById('demo');
    	function rander(){
    		demo.style.left = parseInt(demo.style.left) + 1 + 'px'; //每一帧向右移动1px
    	}
    	requestAnimationFrame(function(){
    		rander();
    		//当超过300px后才停止
    		if(parseInt(demo.style.left)<=300){			
    			requestAnimationFrame(arguments.callee);
    		}
    	});
    </script>
    
  • 相关阅读:
    javaWeb 使用jsp开发 if else 标签
    javaWeb 使用jsp开发 if 标签
    javaWeb 使用jsp标签进行防盗链
    javaWeb 在jsp中 使用自定义标签输出访问者IP
    javaWeb el表达式和jstl快速入门案例
    javaWeb 使用 jsp 和 javaBean 实现计算器功能
    javaWeb 使用cookie显示上次访问网站时间
    javaWeb 使用cookie显示商品浏览记录
    javaWeb request乱码处理
    ubunu下用命令设置壁纸
  • 原文地址:https://www.cnblogs.com/both-eyes/p/12109522.html
Copyright © 2011-2022 走看看