JS实现动画原理一(闭包方式)

前提:

     你必须了解js的闭包(否则你看不懂滴)

    我们就来做一个js实现jq animate的动画效果来简单探索一下,js动画实现的简单原理;

    html代码 <div id="man" style="background:gray; height:1px; 100%;"> </div>

    原理:就是让它的高度逐渐从 1px ----100px

    jq 代码实现:$("#id").animate({height:"100px"})

    JS (too yong too simple) 代码实现方式:

function addHeight(){
    var obj=document.getElementById("man");    
    for(var i=1;i<10;i++){
    var len=i*10;
    obj.style.height=len+"px";
    }
}

    //为什么too young too simple 我不解释;

   JS(sometimes  naive)代码实现方式:

function addHeight2(){
    var obj=document.getElementById("man");    
   for(var i=1;i<10;i++){
    setTimeout(function(){
     var len=i*10;
     obj.style.height=len+"px";
   },i*1000)
 }
}

//为什么说 sometimes naive 呢? 因为你的 i 直接就等10 了 不信你 alert 一下,就是10;

     //这里还需要插播一点关于setTimeout 的使用方法;

      setTimeout 的使用方法

var g=100;
function Test(val){
   alert(val);
}
setTimeout(Test,3000); //三秒手执行
setTimeout(Test(),3000); //马上执行
setTimeout(Test(g),3000); //马上执行

//那么,我们如何传递参数呢;
//方式一(如果是静态参数的话)
setTimeout(function (){
Test("静态参数");
},3000)

//方式二(如果是动态参数)
setTimeout(function (g){
Test(g);
}(g),3000)

//方式三(通用) 这里的参数只能是字符串;
setTimeout("Test("+g+")");

    分析,问什么,i会变成10 呢?

    答案如下:

function addHeight3(){
var obj=document.getElementById("man");    
for(var i=1;i<10;i++){
setTimeout(function(){
         alert(i)                                  //什么变量i是10 呢
                                                    //你可以借助异步的概念来理解;
                                                   //第一次循环 i=1
                                                   //seTimeout 中的 delay=1000
                                                  //在着1000内 循环,早已结束,结果i=10
                                               //现在的问题就是  将 i 传递进去呢;
              },i*1000)
         }
}

 

 改进

function addHeight4(){
var obj=document.getElementById("man");    
   for(var i=1;i<10;i++){
     setTimeout(function(para){
                                           //这样写的话 是可以将参数传递进去,不过函数会立即执行;没有时间间隔!

       alert(para);                  //1 2 3 4 5 6 7 8 9 10
      }(i),i*5000)                  //也就是说,这里的delay 时间设置无效果;
  }
}

     

   最总完整代码:(并不推荐这种方式来实现动画)

function addHeight(){
   var obj=document.getElementById("man");    
     for(var i=1;i<10;i++){
                                            
     setTimeout((function(para){   // 第一个函数(也就是function(para))执行后 ,返回 返回函数引用(函数体) 
         return function (){            //立即执行之后 返回一个匿名函数;
                                   
            var len=para*10;            //这个参数可以理解成 动画元素中帧的概念!
           obj.style.height=len+"px";
          }
     })(i),i*20) //如果想让效果平滑一点,那么 就将时间参数设置小一点呀;
   }
}

//这样就实现jq animate的效果的;

实现不停地变化,我们用setInterval来实现(就是,在最外层嵌套一个seInterval函数;)

扩展

      我们可以使用opacity 来达到渐变的效果的呀;

       代码如下:

function addHeight(){
   var obj=document.getElementById("man");    
     for(var i=1;i<10;i++){
                                            
     setTimeout((function(para){  
         return function (){           
           obj.style.opacity=para;
          }
     })(i/10),i*1000) 
   }
}

 

   总结:

         其实这种实现方式并不是最佳的,最佳实现方式

          情看我的JS-实现动画原理二(非闭包方式)

---------------------------------------------------------------------更新:有了新的方法LET 产生局部变量滴啊;

下边附带各种草稿;

<!DOCTYPE HTML>
<html>

<script>
  //這種閉包的問題還出現在我們的數組中滴呀;
  function fn1(){
  var list = document.getElementById('list1');
  for(var i=1;i<=5;i++){
      var  item = document.createElement('li');
           item.appendChild(document.createTextNode('item ' +i))
           console.log(i);
           item.onclick=function (ev){
            console.log('item' +i+ 'is clicked')
          }
          list.appendChild(item)
      };
   }
  function fn2(){
    var obj=document.getElementById("list1");
    //同樣的問題還出現在我們數組中滴;
    for(var i=0;i<=5;i++){
       setTimeout(function (){
          var len=i*10;
          obj.style.height=len+"px";
          //這裡會執行五次, 這個for循環相當於生成了五個timeout對象;
          //每次都講長度設置為50
          console.log('--');
          
       },i*1000)
    }
  }

  function fn3(){
    
    //只要在我們不用的作用域中就會出現問題;
    var index=1;
    (function (){
      console.log('立即執行')
     console.log(index); //index
     })();
    setTimeout(function (){
      console.log('100s');
      console.log(index);
       index=300;
    },100)

    setTimeout(function (){
      console.log('300s');
      console.log(index);
    },300)

  }

  function fn4(){
    //解決方案1      建立副本
    var index=1;
    setTimeout(function (){
       console.log(index);
       index=300;
       console.log("值被改变了")
    },100)
    //解決方法二 使用快級別作用域
    setTimeout(function (index){
      return function (){
      console.log("使用了闭包中的值value:"+index);
      }
      }(index),500)
  setTimeout(function (){
        console.log("没有使用闭包的值:"+index)

      },400)

  }

  //现在有了新的方法 let使用我们的块级别作用域滴呀;
  function fn5(){
    var list = document.getElementById('list0');
       for(var i=1;i<=5;i++){
         var item=document.createElement("li");
         item.appendChild(document.createTextNode("item" +i));
         //再来绑定我们的额事件滴哎呀;
          (function (index){
             item.onclick=function (ev){
                  console.log(' item '+index)
             }
          })(i)
          list.appendChild(item);
       }

  }

  //形成我们的块级别作用域;
  function fn6(){
     var list=document.getElementById("list0");
     for(let i=1;i<=5;i++){
         var item=document.createElement("li");
          item.appendChild(document.createTextNode("item" +i));
          console.log(i);
          item.onclick=function(ev){
             console.log("item "+i);
          } 
          list.appendChild(item);
     }
  }

  function test(){

    for(var i=1;i<=5;i++){
           setTimeout(function (){
              console.log(i);
           },300*i)
    }

  }

  function test2(){
    for(let i=1;i<=5;i++){
           setTimeout(function (){
                   console.log(i);

           },300*i)
    }

  }

  window.onload=function (){
   //test();
  console.log("--------------")
   test2();

     //fn1(); 
     // fn2(); 
     // fn3();
     //fn4();
     //fn5(); fn 基本能够达到我们想要的基本效果了
    // fn6();
    // 这样,就形成了我们的局部变量;
  }
  


</script>
<body>
   <div id="list0"></div>
   <div id="list1"  style="background-color:red;"></div>
   <div id="list2"></div>
   <div id="list3"></div>
</body>
</html>

 這裡還有一種情況:就是我們數組;

  function showInfo(){
    //现在还有我们想要的基本法则;
     var arr=[];
     for (var i=0;i<5;i++){
        arr[i]=function (){
           return i;
         }
     }

     console.log(arr);
     console.log(arr[0]());
     console.log(arr[1]());

    var arr=[];
     for (var i=0;i<5;i++){
            arr[i]=i; //这里已经进行了赋值操作操作呀;
        }
     
     console.log(arr);
     console.log(arr[0]);
     console.log(arr[1]);
      
      //然后我们通过传递参数的形式

     var arr=[];
     for (var i=0;i<5;i++){
            ///一个立即执行的函数里,返回一个函数;再加上我们的()就执行了的啊;
            arr[i]=(function (index){
                  return function (){
                     return index;
                  }
            })(i)
        }
     
     console.log(arr);
     console.log(arr[0]());
     console.log(arr[1]());
    //当然,最后,可以使用我们es5 中的 let关键之;
  }
原文地址:https://www.cnblogs.com/mc67/p/4801422.html