前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >requestAnimationFrame实现动画效果

requestAnimationFrame实现动画效果

作者头像
OECOM
发布2020-07-02 11:47:33
1.9K0
发布2020-07-02 11:47:33
举报
文章被收录于专栏:OECOMOECOMOECOM

html动画一般会采用css3的形式去做,当然也比较建议用css去做动画。但是有时候一些动画只能使用js来完成,常用的js动画方案是使用计时器来完成。编写动画循环的一个关键在于我们要延迟多长时间比较合适,如何设置时间才能让动画显得平滑顺畅,这个时间并不是越小越好,因为要遛狗足够的时间间隔来让浏览器产生渲染变化,否则就会变成跳跃感。

目前大多数的电脑显示器的刷新频率是60Hz,也就是一秒钟绘制60次,一般我们成为fps。大多数的浏览器都会对重绘操作进行限制,但是不会超过浏览器的频率,即使超过了,用户体验也不会有所提升。因此,最佳的循环时间就是1000/60,大约16.6毫秒。

了解过事件循环机制的朋友应该知道,siteTimeout和setInterval并不是精准的时间间隔,他们要等待其他优先的执行队列执行完成以后才能继续执行。

于是就引入了一个新的动画执行方式-- window.requestAnimationFrame()。它告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。

它采用的是系统时间间隔,以保证最佳的绘制效率,不会因为时间过短造成过度绘制,也不会因为时间间隔太长,产生动画卡顿的现象。让各种网页动画效果能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果。

特点

  • requestAnimationFrame会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率
  • 在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的CPU、GPU和内存使用量
  • requestAnimationFrame是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销

兼容性

具体兼容性如下图所示

应用

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

let retID = requestAnimationFrame(callback);

取消的话可直接使用canceAnimationFrame来进行取消即可

cancelAnimationFrame(retID)

调用一次只会执行一次,所以正确的循环调用方式如下:

var count = 0;
function step() {
    count++;
    console.log(count)
  if (count > 6000) {
    window.cancelAnimationFrame(step);
  }else{
     window.requestAnimationFrame(step);
  }
}
step();

因为requestAnimationFrame有一定的兼容性,所以我们需要对齐进行兼容处理

window.requestAnimat = (function(){
    return window.requestAnimationFrame ||
            window.webkitRequestAnimationFrame  ||
            window.mozRequestAnimationFrame || function(callback){
                setTimeout(callback,1000/60);
            }
        })();
if (!window.cancelAnimationFrame) {
    window.cancelAnimationFrame = function(id) {
        clearTimeout(id);
    };
}

下面来看一下具体的应用效果,下面的示例是模拟一个进度条

<div id="myDiv" style="background-color: lightblue;width: 0;height: 20px;line-height: 20px;">0%</div>
<button id="btn">run</button>
<script>
var timer;
btn.onclick = function(){
    myDiv.style.width = '0';
    cancelAnimationFrame(timer);
    timer = requestAnimationFrame(function fn(){
        if(parseInt(myDiv.style.width) < 500){
            myDiv.style.width = parseInt(myDiv.style.width) + 5 + 'px';
            myDiv.innerHTML =     parseInt(myDiv.style.width)/5 + '%';
            timer = requestAnimationFrame(fn);
        }else{
            cancelAnimationFrame(timer);
        }    
    });
}
</script>
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-02-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 特点
  • 兼容性
  • 应用
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档