为什么要说它,源于看到的一道面试题:问题是用js实现一个无限循环的动画。

首先想到的是定时器

<!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`}}setInterval(function(){render()},1000/60)</script>
</body>
</html>

可以说是完美实现!

至于时间间隔为什么是1000/60,这是因为大多数屏幕渲染的时间间隔是每秒60帧。

既然setInterval可以搞定为啥还要用requestAnimationFrame呢?

不同之处在于,setInterval必须指定多长时间再执行,window.requestAnimationFrame()则是推迟到浏览器下一次重绘时就执行回调。重绘通常是 16ms 执行一次,不过浏览器会自动调节这个速率,比如网页切换到后台 Tab 页时,requestAnimationFrame()会暂停执行。

如果某个函数会改变网页的布局,一般就放在window.requestAnimationFrame()里面执行,这样可以节省系统资源,使得网页效果更加平滑。因为慢速设备会用较慢的速率重流和重绘,而速度更快的设备会有更快的速率。

直接上代码:

注意: requestAnimationFrame()在浏览器重绘前执行,所以要想执行requestAnimationFrame()必须要让浏览器触发重绘。

<!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?是否有类似clearInterval这样的类似方法?

答案是确定的。requestAnimationFrame()返回一个 long 整数,请求 ID ,是回调列表中唯一的标识,是个非零值,没别的意义。你可以传这个值给 window.cancelAnimationFrame() 以取消回调函数。

<!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 rafId = nullfunction 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);//如果left等于50 停止动画if(left == 50){cancelAnimationFrame(rafId)}})();//setInterval效果// setInterval(function(){//     render()// },1000/60)</script>
</body>
</html>

MDN链接

总结:

 function animloop() {console.log('aa')}window.requestAnimationFrame(animloop);

浏览器其实一直在刷新,当给window.requestAnimationFrame传入一个回调函数的时候,那么就是告诉浏览器在渲染前执行一下这个回调函数。


    (function animloop(time) {console.log('time', Date.now())rafId = requestAnimationFrame(animloop);})();

或者

<script>let i= 0;function clock() {console.log(i)window.requestAnimationFrame(clock);}window.requestAnimationFrame(clock);
</script>

上面这段代码只要一执行,那么就会停不下来。
原因是:我们可以把requestAnimationFrame想象成setTimeout,由于requestAnimationFrame并不是在所有的浏览器中都支持,那么我们可以写一个用setTimeout实现的polyfill,而setTimeout又是异步的,所以,进入异步队列后又调用那个回调,这样一直回调下去,所以能够一直执行。

如下:

// 这段代码不全
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;};
}

window.requestAnimationFrame讲解相关推荐

  1. window.requestAnimationFrame

    今天小猪在看一个html5的demo时一直在找他的动画是怎么实现的,按照我的理解就应该是调用setInterval来循环调用动画函数来实现.但是在Demo中就是找不到这个函数.干着急的小猪只好一步一步 ...

  2. 网页性能管理详解:浅谈chrome-Timeline及window.requestAnimationFrame()方法

    你遇到过性能很差的网页吗? 这种网页响应非常缓慢,占用大量的CPU和内存,浏览起来常常有卡顿,页面的动画效果也不流畅. 你会有什么反应?我猜想,大多数用户会关闭这个页面,改为访问其他网站.作为一个开发 ...

  3. window.requestAnimationFrame Web3D渲染帧率控制

    目录 window.requestAnimationFrame简介 定义 语法 参数 返回值 使用注意 两种方式控制帧率 默认帧数中取适当次数更新 用延时控制帧率更新的频率 总结 注意: window ...

  4. window.requestAnimationFrame强大的前端动画神器

    今天介绍一个功能强大的api-window.requestAnimationFrame,它既可以实现如丝般顺滑的动画,又能充当性能优化的利器,还能代替setTimeout,setInterval等定时 ...

  5. 浏览器动画window.requestAnimationFrame

    新手发帖,很多方面都是刚入门,有错误的地方请大家见谅,欢迎批评指正 再看别人现实粒子效果的时候会有以下码代: 1 window.requestAnimationFrame || (window.req ...

  6. 数字滚动原生js的三种方式

    数字滚动原生js的三种方式 让数字滚动的效果简单用计时器setInterval就能轻易的实现,例如 <!DOCTYPE html> <html><head>< ...

  7. JS 动画基础: 细说 requestAnimationFrame

    JS 动画基础: 细说 requestAnimationFrame 文章目录 JS 动画基础: 细说 requestAnimationFrame 简介 参考 完整示例代码 正文 `setInterva ...

  8. js动画requestAnimationFrame详解

    看这篇文章之前我希望你会用setTimeout做简单的动画,也就是利用递归来代替setInterval做动画. requestAnimationFrame() 他的作用就是代替定时器做更加流畅高性能的 ...

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

    HTML5/CSS3时代,我们要在web里做动画选择其实已经很多了: 你可以用CSS3的animattion+keyframes; 你也可以用css3的transition; 你还可以用通过在canv ...

  10. 动画requestAnimationFrame

    前言 在研究canvas的2D pixi.js库的时候,其动画的刷新都用requestAnimationFrame替代了setTimeout 或 setInterval 但是jQuery中还是采用了s ...

最新文章

  1. 一文读懂神经网络初始化!吴恩达Deeplearning.ai最新干货
  2. ARM平台下独占访问指令LDREX和STREX的原理与使用详解
  3. linux内核启动时间优化
  4. mysql学习笔记12 其他函数
  5. CMU本科计算机科学,CMU计算机科学学院本科难录吗?
  6. html字符串变量,字符串变量中的Python HTML
  7. SAP License:SAP系统中的删除命令
  8. 基于swing的java系统_Java实验--基于Swing的简单的歌曲信息管理系统(一)
  9. laravel下载安装
  10. Oracle数据库练习题及答案(个人总结)
  11. 深圳率先立法:支持L3自动驾驶上路,凡公开道路皆可行
  12. 【OpenCV笔记】光流法之金字塔Lucas-Kanade
  13. 当年“你说什么,我都能实现”的软件公司,后来都是怎么死的?
  14. 【杂谈】嵌入式软件数据结构的特点
  15. 如何缓解自己紧张焦虑的情绪?
  16. 中文拼音首字母排序比较器
  17. js图片切换 幻灯片效果
  18. js创建节点及节点操作
  19. 数组(一维数组与二维数组)
  20. nohup 命令简介

热门文章

  1. php 磁盘配额,samba服务器安装+磁盘配额笔记
  2. 计算机的硬盘配额如何更改,磁盘配额怎么设置
  3. Unity游戏神经网络版坦克大战
  4. 在桌面计算机找不到光盘驱动,如何弹出DVD驱动器,没有按钮,我在计算机中找不到DVD驱动器...
  5. Blowfish简介
  6. 微信Mac版客户端(支持查看朋友圈)
  7. 使用setBounds()函数设置Java布局
  8. WPA-PSK无线网络破解原理与过程
  9. 计算机革命的主角和英雄——十大超级老牌黑客
  10. 小沙弥密码箱V1.0