如何使用html5新增的定时器requestanimationframe实现进度条功能?

如何使用html5新增的定时器requestanimationframe实现进度条功能?

在requestAnimationFrame出现之前,我们一般都用setTimeout和setInterval,那么html5为什么新增一个requestAnimationFrame,他的出现是为了解决什么问题?

优势与特点:

1)requestAnimationFrame会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率

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

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

一句话就是:这玩意性能高,不会卡屏,根据不同的浏览器自动调整帧率。如果看不懂或者不理解,也没有什么关系,这玩意跟浏览器渲染原理有关。我们先学会使用它!

如何使用requestAnimationFrame?

使用方式跟定时器setTimeout差不多,不同之处在于,他不需要设置时间间隔参数

   var timer = requestAnimationFrame( function(){
      console.log( '定时器代码' );
    } );

参数是一个回调函数,返回值是一个整数,用来表示定时器的编号.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script>
    window.onload = function(){
      var aInput = document.querySelectorAll( "input" ),
        timer = null;
      aInput[0].onclick = function(){
        timer = requestAnimationFrame( function say(){
          console.log( 1 );
          timer = requestAnimationFrame( say );
        } );
      };
      aInput[1].onclick = function(){
        cancelAnimationFrame( timer );
      }
    }
  </script>
</head>
<body>
  <input type="button" value="开启">
  <input type="button" value="关闭">
</body>
</html>

cancelAnimationFrame用来关闭定时器

这个方法需要处理兼容:

简单的兼容:

 window.requestAnimFrame = (function(){
 return window.requestAnimationFrame    ||
     window.webkitRequestAnimationFrame ||
     window.mozRequestAnimationFrame  ||
     function( callback ){
      window.setTimeout(callback, 1000 / 60);
     };
})();

如果浏览器都不认识AnimationFrame,就用setTimeout兼容.

运用3种不同的定时器(setTimeout, setInterval, requestAnimationFrame)实现一个进度条的加载

一、setInterval方式:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    div{
      width:0px;
      height:40px;
      border-radius:20px;
      background:#09f;
      text-align:center;
      font:bold 30px/40px '微软雅黑';
      color:white;
    }
  </style>
  <script>
    window.onload = function(){
      var oBtn = document.querySelector( "input" ),
        oBox = document.querySelector( "div" ),
        timer = null, curWidth = 0,
        getStyle = function( obj, name, value ){
          if( obj.currentStyle ) {
            return obj.currentStyle[name];
          }else {
            return getComputedStyle( obj, false )[name];
          }
        };
      oBtn.onclick = function(){
        clearInterval( timer );
        oBox.style.width = '0';
        timer = setInterval( function(){
          curWidth = parseInt( getStyle( oBox, 'width' ) );
          if ( curWidth < 1000 ) {
            oBox.style.width = oBox.offsetWidth + 10 + 'px';
            oBox.innerHTML = parseInt( getStyle( oBox, 'width' ) ) / 10 + '%';
          }else {
            clearInterval( timer );
          }
        }, 1000 / 60 );
      }
    }
  </script>
</head>
<body>
  <div>0%</div>
  <p><input type="button" value="ready!Go"></p>
</body>
</html>

如何使用html5新增的定时器requestanimationframe实现进度条功能?

二、setTimeout方式

<script>
    window.onload = function(){
      var oBtn = document.querySelector( "input" ),
        oBox = document.querySelector( "div" ),
        timer = null, curWidth = 0,
        getStyle = function( obj, name, value ){
          if( obj.currentStyle ) {
            return obj.currentStyle[name];
          }else {
            return getComputedStyle( obj, false )[name];
          }
        };
      oBtn.onclick = function(){
        clearTimeout( timer );
        oBox.style.width = '0';
        timer = setTimeout( function go(){
          curWidth = parseInt( getStyle( oBox, 'width' ) );
          if ( curWidth < 1000 ) {
            oBox.style.width = oBox.offsetWidth + 10 + 'px';
            oBox.innerHTML = parseInt( getStyle( oBox, 'width' ) ) / 10 + '%';
            timer = setTimeout( go, 1000 / 60 );
          }else {
            clearInterval( timer );
          }
        }, 1000 / 60 );
      }
    }
  </script>

三、requestAnimationFrame方式

 <!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    div{
      width:0px;
      height:40px;
      border-radius:20px;
      background:#09f;
      text-align:center;
      font:bold 30px/40px '微软雅黑';
      color:white;
    }
  </style>
  <script>
    window.onload = function(){
      var oBtn = document.querySelector( "input" ),
        oBox = document.querySelector( "div" ),
        timer = null, curWidth = 0,
        getStyle = function( obj, name, value ){
          if( obj.currentStyle ) {
            return obj.currentStyle[name];
          }else {
            return getComputedStyle( obj, false )[name];
          }
        };
      oBtn.onclick = function(){
        cancelAnimationFrame( timer );
        oBox.style.width = '0';
        timer = requestAnimationFrame( function go(){
          curWidth = parseInt( getStyle( oBox, 'width' ) );
          if ( curWidth < 1000 ) {
            oBox.style.width = oBox.offsetWidth + 10 + 'px';
            oBox.innerHTML = parseInt( getStyle( oBox, 'width' ) ) / 10 + '%';
            timer = requestAnimationFrame( go );
          }else {
            cancelAnimationFrame( timer );
          }
        } );
      }
    }
  </script>
</head>
<body>
  <div>0%</div>
  <p><input type="button" value="ready!Go"></p>
</body>
</html>