
前言我在学习canvas动画的时候看到了requestAnimationFrame之前只学习过定时器故对其进行了深度学习现在终于抽出时间对其进行总结。博客内容不一定完全正确希望给看到的人一点参考共同学习。介绍产生背景在没有requestAnimationFrame的时候通过js实现动画效果一般使用的是定时器特别是循环定时器 Interval 但因为定时器是异步任务其会参与浏览器任务队列这就可能会造成本因在16ms执行的任务因为一些其它异步任务的执行而推迟、被插队等不能准确执行使动画有撕裂感、不流畅。requestAnimationFrame就是为解决这个问题而诞生的。解决的问题时序不同步定时器和屏幕刷新节奏脱节易掉帧、画面抖动。计时不准受主线程阻塞影响间隔不稳定动画卡顿。资源浪费页面切后台仍持续运行额外消耗 CPU 与电量。渲染低效执行时机混乱频繁触发不必要的重排、重绘。使用下面将介绍一下如何使用具体的原理后面会讲QaQrAF的使用很简单和setInterval很像function animation(time){ // 需要执行的动画操作 ..... let rAF requestAnimationFrame(animation) // 这里会循环重复调用是因为rAF函数是一个单次调用的函数 }它的执行时间间隔为16.67ms即每一帧执行一次后面执行时机会详细介绍一下。执行一次后会看还有没有待执行的非同级requestAnimationFrame如果有就会在16.67ms后执行。一个简单示例实现进度条!DOCTYPE html html langen head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 titleDocument/title style .container{ width: 400px; height: 40px; border-radius: 10px; background-color: rgba(255,200,200,0.5); border: 2px solid skyblue; } .item{ height: 100%; width: 0; background-color: rgb(250, 151, 168); border-radius: 10px; } /style /head body div classcontainer div classitem /div /div script const item document.querySelector(.item) function dragMove(){ let w parseInt(item.style.width)|0 if(w 400){ item.style.width w 1 px requestAnimationFrame(dragMove) } } dragMove() /script /body /htmlrAF的执行时机接下来介绍一下rAF的执行时机用于解释为什么它可以解决定时器存在的一些问题浏览器帧在看rAF执行时机之前先看一下浏览器帧(Frame)是什么1帧 浏览器屏幕刷新一次60HZ屏幕 1帧16.67ms每一帧浏览器需要做的工作执行 JS 代码DOM 树更新计算样式CSSOM布局重排 reflow绘制重绘 repaint图层合成 渲染到屏幕这就解释了为什么rAF是没16.67ms执行一次即每一帧执行一次rAF执行时机rAF 的执行时机在一帧的最开始样式计算 / 布局 / 绘制 之前执行。更精准的描述浏览器准备开始新一帧 → 首先执行 rAF 回调 → 执行完后才进行样式计算、布局、绘制。rAF每一帧执行一次不参与任务队列就完美解决了定时器可能存在的延迟问题总结这两周把canvas学习完了也做了不少案例本来打算直接去学习pixiJS的但看了一下学习性价比暂时对外来说不高所以接下来还是继续学习vue3源码吧vite也可以提上日程了同时继续复习js。加油❤