requestAnimationFrame
语法: long window.requestAnimationFrame(callback); void window.cancelAnimationFrame(long); //取消动画
参数: callback 动画回调函数
返回值:long 指的是 callback 在浏览器回调列表中的一个标识,可以用来取消回调函数。
1. 无需计算回调时间,动画的流畅性更有保障。
-- 无论是setTimeout或者是setInterval都需要指明浏览器回调函数的时间。尽管设置了1000/60的回调时间,也就是每秒60帧的动画,但是并不能保证浏览器的真实回调时间,可能会造成动画卡顿。
requestAnimationFrame 不需要设置回调时间,跟着浏览器的重绘的钩子走。这种做法更加高效,不会失帧或者卡顿,更大程度的保证了动画的流畅性。
2. 性能优秀,占用更少内存。
-- 对隐藏或者不可见元素的动画,requestAnimationFrame 不会进行重绘或者是回流,意味着占用的内存更少,性能更好。
1 /**
2 * scrollHeight: 目标高度
3 * duration: 持续时间 ms
4 **/
5
6 function scrollTo(scrollHeight, duration) {
7 let from = window.scrollY;
8 let to = scrollHeight - window.scrollY;
9 lastTimestamp = performance.now(); //上一次动画的时间
10 let fps = 0; //总帧数
11 let currentFPS = 0; //当前帧数
12
13 const step = function (newTimestamp) {
14 //计算出总帧数,由于每次调用的时间不确定,也就是每次调用时距离上一次用用的时间差不确定,
15 //为了确保动画执行的时间和连续性,所以总帧数每次都需要重新计算
16 fps = Math.round(duration/Math.abs(newTimestamp - lastTimestamp ));
17
18 //如果当前帧数等于总帧数,则直接滚动到目标高度,跳出函数,动画结束
19 if(currentFPS >= fps){
20 window.scrollTo(0, scrollHeight);
21 return;
22 }
23 // 计算出当前这一帧动画的位移(或者是角度等等..)
24 // 执行动画
25 let displacement = Tween.Quad.easeInOut(currentFPS, from, to, fps);
26 window.scroll(0, displacement);
27 // 当前帧数自加,更新本次动画的时间,用作下一次计算
28 currentFPS++;
29 lastTimestamp = newTimestamp;
30 //进行下一帧动画
31 window.requestAnimationFrame(step);
32 }
33 window.requestAnimationFrame(step);
34 }
2. 取消动画操作:
html
1 <button id="stopBtn">stop<button> 2 <button id="startBtn">start<button>
css
1 div {
2 width: 10px;
3 height: 10px;
4 background: #ffd213;
5 }
js
1 var animationId; 2 var stop = document.getElementById('stopBtn'); 3 var start = document.getElementById('startBtn'); 4 5 function createBar() { 6 document.body.append(document.createElement('div')); 7 animationId = requestAnimationFrame(createBar); 8 } 9 animationId = requestAnimationFrame(createBar); 10 11 stop.addEventListener('click', function() { 12 cancelAnimationFrame(animationId); 13 }); 14 15 start.addEventListener('click', function() { 16 animationId = requestAnimationFrame(createBar); 17 });