JS实现动画

版权声明:哼!坏人!这是我辛辛苦苦码的! https://blog.csdn.net/DurianPudding/article/details/87937938

三种方式

setTimeout
setInterval
requestAnimationFrame

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    #myDiv {
      background: yellowgreen;
      height: 100px;
      width: 100px;
    }
  </style>
</head>
<body>
<h1>JS实现动画</h1>
<pre>基础:<a href="https://juejin.im/post/59e85eebf265da430d571f89" target="_blank">js执行机制</a></pre>
<h2>1.setTimeout</h2>
<p>例子一:设置x秒后显示</p>
<button id="my-btn">点我</button>
<p id="message" style="display: none">啊!我显示了!</p>

<p>例子二:重复调用setTimeout实现向右推动</p>
<div id="myDiv" style="left: 1px; position: relative;"></div>
<pre>js在JavaScript中,通过document.getElementById(id).style.XXX可以获取到XXX的值,
  但意外的是这样做只能取到通过 内嵌方式 设置的样式值,即style属性里面设置的值。</pre>

<p>例子三(打开控制台查看)</p>
<h2>2.setInternal</h2>
<p>定义:将定时器代码规则的插入队列中。</p>
<p>规则:仅当没有setInterval的任何其他代码实例时,才将定时器代码添加到队列中。</p>
<pre>即:当定时器代码要插入队列时,已经有一个定时器代码 正在运行,并且有一个 定时器实例 在等待,则此处不插入,跳过。</pre>
<p>缺点:1.某些间隔会被跳过 2.多个定时器的代码执行之间的间隔可能比预期的小。</p>
<p>解决:使用链式setTimeout,见例二</p>

<h2>3.requestAnimationFrame</h2>
<pre>参考:<a href="https://www.cnblogs.com/xiaohuochai/p/5777186.html" target="_blank"></a></pre>
<p>最大区别:采用系统时间间隔,最佳绘制。使用一个回调函数作为参数,这个回调函数会在浏览器重绘之前调用。</p>
<pre>
  【1】requestAnimationFrame会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率

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

  【3】requestAnimationFrame是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销
</pre>
<script>
  // setTimeout 1.
  var btn = document.getElementById("my-btn");
  btn.onclick = function(){ // 给一个按钮设置了一个事件处理程序
    setTimeout(function () { // 事件处理程序设置了一个250ms后调用的定时器
      // 对setTimeout的调用表示要晚点执行某些代码
      document.getElementById("message").style.display = "block";
    }, 250); // 重要!!!此处的时间间隔表示何时将定时器的代码添加到队列,而不是何时实际执行代码!
  };


  // setTimeout 2.
  setTimeout(function(){
    var div = document.getElementById("myDiv");
    left = parseInt(div.style.left) + 1;
    div.style.left = left + "px";

    if (left < 200){
      // 链式setTimeout,解决setInterval忽略时间间隔的问题
      setTimeout(arguments.callee, 15);
    }
  }, 15);

  //setTimeout 3:先输出0 后输出2
  var Timer = setTimeout(function(){
    console.log(Timer);
  }, 1000);
  console.log(0);

  // requestAnimationFrame 1:先输出1,后输出0
  // requestID = requestAnimationFrame(callback);
  // requestAnimationFrame使用一个回调函数作为参数,这个回调函数会在浏览器重绘之前调用。
  // 它返回一个整数,表示定时器的编号,这个值可以传递给cancelAnimationFrame用于取消这个函数的执行
  var timer = requestAnimationFrame(function() {
    console.log(0); // 0
  });
  console.log(timer); // 1

  // cancelAnimationFrame方法用于取消定时器
  var timer = requestAnimationFrame(function(){
    console.log(0);
  });
  cancelAnimationFrame(timer);

  //   也可以直接使用返回值进行取消
  var timer = requestAnimationFrame(function(){
    console.log(0);
  });
  cancelAnimationFrame(1);
</script>
</body>
</html>

下面是三种方法的实例:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>进度条-setInterval</title>
</head>
<body>
<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(){
    // 取消对应的定时器,注意与clearTimeout不一样
    clearInterval(timer);
    // 注意是字符串,给parseInt用
    myDiv.style.width = '0';
    timer = setInterval(function(){
      // parseInt解析一个字符串,返回一个整数
      if(parseInt(myDiv.style.width) < 500){
        myDiv.style.width = parseInt(myDiv.style.width) + 5 + 'px';
        // 总长500,除以5的数字正好是百分比
        myDiv.innerHTML =     parseInt(myDiv.style.width)/5 + '%';
      }else{
        clearInterval(timer);
      }
    },16);
  }
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>setTimeout-进度条</title>
</head>
<body>
<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() {
    // 注意与clearInterval不一样
    clearTimeout(timer);
    myDiv.style.width = '0';
    // 给function取个名字后面链式用
    timer = setTimeout(function fn(){
      if(parseInt(myDiv.style.width) < 500) {
        myDiv.style.width = parseInt(myDiv.style.width) + 5 + 'px';
        myDiv.innerHTML = parseInt(myDiv.style.width)/5 + '%';
        // 链式setTimeout
        timer = setTimeout(fn,16);
      } else {
        clearTimeout(timer);
      }
    },16)
  }
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>requestAnimationFrame-进度条</title>
</head>
<body>
<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(){
    // 注意cancelAnimationFrame
    cancelAnimationFrame(timer);
    myDiv.style.width = '0';
    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 + '%';
        // requestAnimationFrame只传入一个参数
        timer = requestAnimationFrame(fn);
      } else {
        cancelAnimationFrame(timer);
      }
    }) // 只传入一个参数
  }
</script>
</body>
</html>

猜你喜欢

转载自blog.csdn.net/DurianPudding/article/details/87937938
今日推荐