关于 requestAnimationFrame()和setInterval
前言:学习canvas制作JS动画,基本使用的都是定时器setInterval(),但是忽然发现了一个比较好的canvas动画使用的requestAnimationFrame,之前在开课吧的JS教学视频接触过这个方法,但是忽然忘了。立马进行了百度,找到了一篇讲的比较清晰的文章。以下仅作为笔记,如侵权,请联系删除
链接地址:https://www.jianshu.com/p/fa5512dfb4f5
requestAnimationFrame 比起 setTimeout、setInterval的优势主要有两点:
1、requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。
2、在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。
一、开始使用
原博文代码:
<!doctype html>
<html lang="en">
<head>
<title>Document</title>
<style>
#e{
width: 100px;
height: 100px;
background: red;
position: absolute;
left: 0;
top: 0;
zoom: 1;
}
</style>
</head>
<body>
<div id="e"></div>
<script>
var e = document.getElementById("e");
var flag = true;
var left = 0;
function render() {
if(flag == true){
if(left>=100){
flag = false
}
e.style.left = ` ${left++}px`
}else{
if(left<=0){
flag = true
}
e.style.left = ` ${left--}px`
}
}
//requestAnimationFrame效果
(function animloop() {
render();
window.requestAnimationFrame(animloop);
})();
</script>
</body>
</html>
二、停止 requestAnimationFrame()方法:cancelAnimationFrame()
cancelAnimationFrame()接收一个参数 requestAnimationFrame默认返回一个id,cancelAnimationFrame只需要传入这个id就可以停止了,和定时器一样
原代码:
<!doctype html>
<html lang="en">
<head>
<title>Document</title>
<style>
#e {
width: 100px;
height: 100px;
background: red;
position: relative;
left: 0;
top: 0;
zoom: 1;
}
</style>
</head>
<body>
<button onclick="stop()">停止动画</button>
<div id="e"></div>
<script>
var e = document.getElementById("e");
var flag = true;
var left = 0;
var rafId = null;
function render() {
if (flag == true) {
if (left >= 100) {
flag = false
}
e.style.left = ` ${left++}px`
} else {
if (left <= 0) {
flag = true
}
e.style.left = ` ${left--}px`
}
}
//requestAnimationFrame效果
(function animloop(time) {
console.log(time, Date.now())
render();
rafId = requestAnimationFrame(animloop);
})();
function stop() {
cancelAnimationFrame(rafId)
}
</script>
</body>
</html>
三、requestAnimationFrame()类似 setInterval() 改变动画时间间隔
原博文代码:
<!doctype html>
<html lang="en">
<head>
<title>Document</title>
<style>
#e{
width: 100px;
height: 100px;
background: red;
position: absolute;
left: 0;
top: 0;
zoom: 1;
}
</style>
</head>
<body>
<div id="e"></div>
<script>
var e = document.getElementById("e");
var flag = true;
var left = 0;
//当前执行时间
var nowTime = 0;
//记录每次动画执行结束的时间
var lastTime = Date.now();
//我们自己定义的动画时间差值
var diffTime = 40;
function render() {
if(flag == true){
if(left>=100){
flag = false
}
e.style.left = ` ${left++}px`
}else{
if(left<=0){
flag = true
}
e.style.left = ` ${left--}px`
}
}
//requestAnimationFrame效果
(function animloop() {
//记录当前时间
nowTime = Date.now()
// 当前时间-上次执行时间如果大于diffTime,那么执行动画,并更新上次执行时间
if(nowTime-lastTime > diffTime){
lastTime = nowTime
render();
}
requestAnimationFrame(animloop);
})()
</script>
</body>
</html>
后记:
在JS动画中使用定时器或requestAnimationFrame()的选择上,requestAnimationFrame()的好处上面已经提过,不再赘述。唯一的一点不好的地方就是时间间隔上不如定时器的设定那么方便。多个方法多条路,选择那个关键还是看项目中的运用了。