requestAnimationFrame 请求动画帧

它是一个浏览器的宏任务

requestAnimationFrame的用法与settimeout很相似,只是不需要设置时间间隔而已。requestAnimationFrame使用一个回调函数作为参数,这个回调函数会在浏览器重绘之前调用。它返回一个整数,表示定时器的编号,这个值可以传递给cancelAnimationFrame用于取消这个函数的执行

requestAnimationFrame特点

【1】requestAnimationFrame会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,如果系统绘制率是 60Hz,那么回调函数就会16.7ms再 被执行一次,如果绘制频率是75Hz,那么这个间隔时间就变成了 1000/75=13.3ms。换句话说就是,requestAnimationFrame的执行步伐跟着系统的绘制频率走。它能保证回调函数在屏幕每一次的绘制间隔中只被执行一次,这样就不会引起丢帧现象,也不会导致动画出现卡顿的问题。

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

【3】requestAnimationFrame是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销

跟setTimeout和setInterva的对比

setTimeout和setInterval的问题是,它们都不精确。它们的内在运行机制决定了时间间隔,参数实际上只是指定了把动画代码添加到浏览器UI线程队列中以等待执行的时间。如果队列前面已经加入了其他任务,那动画代码就要等前面的任务完成后再执行

requestAnimationFrame采用系统时间间隔,保持最佳绘制效率,不会因为间隔时间过短,造成过度绘制,增加开销;也不会因为间隔时间太长,使用动画卡顿不流畅,让各种网页动画效果能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果

IE9-浏览器不支持该方法,可以使用setTimeout来兼容

//简单兼容
if (!window.requestAnimationFrame) {requestAnimationFrame = function(fn) {setTimeout(fn, 17);};
}
//严格兼容 , 因为setTimeout内部运行也需要时间,以及需要给回调的第一个参数返回时间戳
if(!window.requestAnimationFrame){var lastTime = 0;window.requestAnimationFrame = function(callback){var currTime = new Date().getTime();var timeToCall = Math.max(0,16.7-(currTime - lastTime));var id  = window.setTimeout(function(){callback(currTime + timeToCall);},timeToCall);lastTime = currTime + timeToCall;return id;}
}

应用场景

1、监听 scroll 函数

页面滚动事件(scroll)的监听函数,就很适合用这个 api,推迟到下一次重新渲染。

$(window).on('scroll', function () {window.requestAnimationFrame(scrollHandler)
})

平滑滚动到页面顶部

const scrollToTop = () => { const c = document.documentElement.scrollTop || document.body.scrollTop if (c > 0) {  window.requestAnimationFrame(scrollToTop) window.scrollTo(0, c - c / 8) }
}scrollToTop()

2、大量数据渲染

比如对十万条数据进行渲染,主要由以下几种方法:

(1)使用定时器

//需要插入的容器
let ul = document.getElementById('container')
// 插入十万条数据
let total = 100000
// 一次插入 20 条
let once = 20
//总页数
let page = total / once
//每条记录的索引
let index = 0
//循环加载数据
function loop(curTotal, curIndex) { if (curTotal <= 0) {  return false }  //每页多少条let pageCount = Math.min(curTotal, once) setTimeout(() => {  for (let i = 0; i < pageCount; i++) { let li = document.createElement('li')    li.innerText = curIndex + i + ' : ' + ~~(Math.random() * total)    ul.appendChild(li)  }  loop(curTotal - pageCount, curIndex + pageCount) }, 0)
}
loop(total, index)

(2)使用 requestAnimationFrame

//需要插入的容器
let ul = document.getElementById('container')
// 插入十万条数据
let total = 100000
// 一次插入 20 条
let once = 20
//总页数
let page = total / once
//每条记录的索引
let index = 0
//循环加载数据
function loop(curTotal, curIndex) {if (curTotal <= 0) {return false}//每页多少条let pageCount = Math.min(curTotal, once)window.requestAnimationFrame(function () {for (let i = 0; i < pageCount; i++) {let li = document.createElement('li')li.innerText = curIndex + i + ' : ' + ~~(Math.random() * total)ul.appendChild(li)}loop(curTotal - pageCount, curIndex + pageCount)})
}
loop(total, index)

3、监控卡顿方法
每秒中计算一次网页的 FPS,获得一列数据,然后分析。通俗地解释就是,通过 requestAnimationFrame API 来定时执行一些 JS 代码,如果浏览器卡顿,无法很好地保证渲染的频率,1s 中 frame 无法达到 60 帧,即可间接地反映浏览器的渲染帧率。

var lastTime = performance.now()
var frame = 0
var lastFameTime = performance.now()
var loop = function (time) {var now = performance.now()var fs = now - lastFameTimelastFameTime = nowvar fps = Math.round(1000 / fs)frame++if (now > 1000 + lastTime) {var fps = Math.round((frame * 1000) / (now - lastTime))frame = 0lastTime = now}window.requestAnimationFrame(loop)
}

我们可以定义一些边界值,比如连续出现 3 个低于 20 的 FPS 即可认为网页存在卡顿。

requestAnimationFrame,读懂这篇文章就够了相关推荐

  1. (转载)2010年股市只要读懂这篇文章想亏钱都难

    一,赢家重在观念正确 1 一年做一股!忠告,轻易不抛牛股,毕业.首选牛股.得半道,热点与强势股兼做,投资投机两相宜.得全道 2 操盘手最重要的是盘中的应变能力 3 定性是必须做好的.大周期定性,周线选 ...

  2. 读懂这篇文章就懂大数据,3000字概括《大数据时代》

    有言在先 近期有些起伏,这种情况最适合回归书本,寻找一些你内心认同的东西.这几天花了点时间重温<大数据时代>,整理.总结出了精华的东西,分享给大家. 大数据引起了变革 当今社会所独有的一种 ...

  3. 入门响应式Web?看懂这篇文章就够了!——Web前端系列学习笔记

    文章目录 视口基础知识 视口概念 视口基本属性 meta 标签 视口应用实例 媒体查询基础知识 媒体查询概念 demo1-媒体查询 demo1效果 百分比布局 百分比布局概述 demo2-百分比布局 ...

  4. 入门JavaScript?看懂这篇文章就够了!——Web前端系列学习笔记

    文章目录 JavaScript简介 什么是JavaScript? JavaScript的构成 JavaScript特点 JavaScript基础知识 JavaScript的引入方式 1. 将JS代码嵌 ...

  5. 读懂这篇文章,你的阿里技术面就可以过关了 | Apache RocketMQ 101

    在美国的大学课程中,101是所有课程中的第一门,是新生入学后的必修课程.阿里巴巴中间件技术专家刘振东在上周的Apache RocketMQ开发者沙龙北京站的活动上,进行了主题为<ApacheRo ...

  6. 读懂这篇文章,你就懂了全网通5.0

    上个月,千元标杆红米Note 5发布,新机支持全网通5.0,双卡双待4G,一边打电话一边打游戏也不会掉线. 那么相比小米去年推出的全网通4.0,全网统5.0有哪些进化呢?官方整理了"六问六答 ...

  7. 使用分层网络模型的两个优点是什么_从零开始学网络|搞懂OSI参考模型和TCP/IP分层模型,看这篇文章就够了...

    从零开始学网络|搞懂OSI参考模型和TCP/IP分层模型,看这篇文章就够了​mp.weixin.qq.com 前言 今天和大家一起谈谈"网络",之前写的文章可能不太通俗易懂,有人就 ...

  8. 看懂这篇文章,你就懂了信息安全的密码学

    看懂这篇文章-你就懂了信息安全的密码学 一.前言 ​ 一个信息系统缺少不了信息安全模块,今天就带着大家全面了解并学习一下信息安全中的密码学知识,本文将会通过案例展示让你了解抽象的密码学知识,阅读本文你 ...

  9. 万字心得,PMP学习考试那些事儿,看这篇文章就够了

    声明:文章为原创,首发于知乎,链接:万字长文!PMP考试那些事儿,看这篇文章就够了 - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/524966002 以下内 ...

最新文章

  1. 新成立的Scala中心将重点关注教育和Scala社区
  2. Arduino的光敏传感器和超声波测距传感器测试代码
  3. 蓝桥杯_算法训练_ALGO12_摆动序列
  4. 【版本更新】IM 4.3.0新版本升级上线!
  5. IIS负载均衡-Application Request Route详解第三篇:使用ARR进行Http请求的负载均衡
  6. 二分查找非递归方式实现
  7. dataframe 空值替换为0_dataframe取元素方法总结
  8. 有机晶体数据库_Cambridge Structural Database 2017 晶体结构分析软件分享
  9. Flutter 底部弹框 showModalBottomSheet 使用Demo
  10. linux安装jdk环境
  11. 5元以下纯铜小摆件_【拍4斤发5斤】早餐饼干网红早餐代餐曲奇酥性小饼干零食500g6元优惠券券后价5.8元...
  12. Kaggle比赛(一)Titanic: Machine Learning from Disaster
  13. web前端好入门吗?
  14. wxpython 调用子窗口_wxpython简介
  15. 迅雷精简版 for Mac!附精简教程!
  16. 二乘二(二阶)魔方教程,看完教程拼不出来我给你钱!
  17. 程序员,要不要考软考高级职称?
  18. 智能路由器OpenWrt 开发环境 及 编译分析(一)
  19. 简述卡西欧5800p计算机,fx5800p
  20. C#实现时间戳与标准时间的互转学习通http://www.bdgxy.com/

热门文章

  1. h5仿android 京东三级联动,jquery仿京东商城三级联动代码插件
  2. STM32F429第二十三篇之电容按键
  3. 给企业管理者的忠告《原则》作者瑞·达利欧
  4. 关于波兰式、逆波兰式
  5. Unity3D游戏开发之塔防游戏项目讲解(下)
  6. Azure基础:什么是Azure 区域、可用性区域和区域对(14)
  7. python根据坐标点画线_Openlayers 根据坐标点画点线圆多边形
  8. AEC——智慧物流管理系统
  9. R语言随机搜索变量选择SSVS估计贝叶斯向量自回归(BVAR)模型
  10. Gerrit version 2.12.9 is now available