requestAnimationFrame是HTML5用于浏览器为动画提供API(类似setTimeout定时器)的一种刷新机制,根据设备的屏幕刷新频率有关,例如:60Hz 的刷新频率就相当于一秒刷新60次,平均16.7ms执行一次。

setTimeout不一样的是:不需要设置时间间隔,如同上面说的,默认间隔是由设备系统的屏幕刷新频率决定的。

requestAnimationFrame用法

let raf = window.requestAnimationFrame(fun) //接受一个回调函数,返回一个数字类型的动画id

执行动画如果不做防抖处理,也会和setTimeout一样,动画越来越快——“被加速”,使用的时候一定要注意。

清除requestAnimationFrame动画需要用cancelAnimationFrame,如下:

window.cancelAnimationFrame(raf)

动画案例

利用requestAnimationFrame实现一个盒子移动的动画,left小于500的时候终止动画,代码如下:

HTML代码:

<style type="text/css">
#box{width: 100px;height: 100px;background: red;position: absolute;left: 0;top: 50px;}
</style>
<button onclick="start()">start</button>
<button onclick="end()">end</button>
<div id="box"></div>

JS代码

let lefts = 0,tops=0,ref,flag = false;
let box = document.getElementById("box")
function move(){
	if(lefts<500 ){
		lefts++;
		tops=tops+1;
	}else{
		lefts = 0
		tops = 0
	}
	box.style.left=lefts+'px'
	box.style.top=tops+'px'
	ref = window.requestAnimationFrame(move)
}
function end(){
	if(ref){
		flag = false
		window.cancelAnimationFrame(ref)
	}
}
function start(){
	//防抖,不然动画会越来越快
	if(!flag){
		flag = true
		ref = window.requestAnimationFrame(move)
	}
}


效果如下:
HTML5动画API:requestAnimationFrame和cancelAnimationFrame使用-QUI-Notes

关于兼容性
现代浏览器随便玩,毕竟是HTML5官方的api,支持率还是可以的,如果是老版本内核,或者IE系列的话还是需要回退到setTimeout定时器时代。网上有以下兼容代码,可以借鉴:

// 使用 Date.now 获取时间戳性能比使用 new Date().getTime 更高效
if (!Date.now)
  Date.now = function() {
    return new Date().getTime();
  };
(function() {
  "use strict";
  var vendors = ["webkit", "moz"];
  for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
    var vp = vendors[i];
    window.requestAnimationFrame = window[vp + "RequestAnimationFrame"];
    window.cancelAnimationFrame =
      window[vp + "CancelAnimationFrame"] ||
      window[vp + "CancelRequestAnimationFrame"];
  }
  // 上面方法都不支持的情况,以及IOS6的设备
  // 使用 setTimeout 模拟实现
  if (
    /iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) ||
    !window.requestAnimationFrame ||
    !window.cancelAnimationFrame
  ) {
    var lastTime = 0;
    // 和通过时间戳实现节流功能的函数相似
    window.requestAnimationFrame = function(callback) {
      var now = Date.now();
      var nextTime = Math.max(lastTime + 16, now);
      // 实际上第1帧是不准确的,首次nextTime - now = 0
      return setTimeout(function() {
        callback((lastTime = nextTime));
      }, nextTime - now);
    };
    window.cancelAnimationFrame = clearTimeout;
  }
})();

以上就是requestAnimationFrame简单的用法了,可以利用这个刷新机制使svg,canvas,Dom等动起来,大家学起来,用起来!2023年的第一篇文章,又是从新开始的一年,也是学习不停的一年,加油!