控制requestAnimationFrame按秒执行

requestAnimationFrame

requestAnimationFrame() 他的作用就是代替定时器做更加流畅高性能的动画,做可以匹配设备刷新率的动画,他解决了定时器做动画时间间隔不稳定的问题(也就是解决定时器做动画不流畅的问题)。他的用法与setTimeout差不多。

与setTimeout一样的是都会返回一个唯一标识,setTimeout可以通过clearTImeout()关闭定时器。那么requestAnimationFrame()使用的就是cancelAnimationFrame()关闭动画。

不同的是这个方法你只需要传入一个回调函数,不需要其他参数,那么你就疑惑了不用指定时间间隔怎么做动画??

时间间隔自然是有的,但时间间隔由设备的系统决定(不受其他任务的影响)。通常来你传入的回调函数每秒会执行60次,但是如果你的设备的游览器遵循W3c的标准,那么回到函数每秒执行的次数会与你设备的刷新率相匹配。不仅如此这还是一个高性能的方法,在大多游览器中一旦页面不处于浏览器的当前标签,就会自动停止动画。

如果我们使用定时器setTimeout做动画,我们假设显示器的刷新率为60hz(60hz指的是每秒1播放60张动画)。为了让动画显示流畅,我们需要将定时器setTimeout的间隔时间定位 “1000/60” 也就1秒执行60次回调函数,大约每隔16.67毫秒会执行一次,这样就能匹配显示屏的帧率。看似好像完美匹配了其实还会有卡顿问题,因为定时器属于宏任务,而宏任务必须等待同步任务执行完成,再等微任务执行完成才会执行其中的回调函数,所以你规定的时间间隔是不稳定不准确的。

requestAnimationFrame可以用来取代setTimeout,但是它不能像setTimeout一样设置时间间隔
以下方法通过加时间戳来实现,1秒执行一次
复制代码
 function start_animate(duration){
      let d = document.getElementById('test');
      let myStyle = null;
      //获取样式
      if(document.defaultView){
        myStyle = document.defaultView.getComputedStyle(d,null)
      }else{
        //IE
        myStyle = d.currentStyle
      }
      let requestID
      let startTime =null
      let time = null
      //动画函数
      let animate = function(d,myStyle){
        time = new Date().getTime()
        if(startTime===null){
          startTime = time
        }

        if(time-startTime>=duration){
          //条件满足
          startTime = time
          let h= parseInt(myStyle.height)+10
          if(h<200){
            d.style.height = h+'px'
            requestID = requestAnimationFrame(()=>{animate(d,myStyle)})
          }
        }else{
          //不满足
          requestID&&cancelAnimationFrame(requestID)
          requestID = requestAnimationFrame(()=>{animate(d,myStyle)})
        }
      }

      //初始调用
      requestID = requestAnimationFrame(()=>{animate(d,myStyle)})
      animate(d,myStyle)
    }
    start_animate(1000)
复制代码

 

posted @   lijun12138  阅读(853)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示