zoukankan      html  css  js  c++  java
  • 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关键之;
      }
  • 相关阅读:
    [Angular] How to show global loading spinner for application between page navigation
    [NgRx] NgRx Data Fetching Solution
    [NgRx] NgRx Entity Adapter Configuration
    [Javascript] Construct a Regex to Match Twitter Mentions with Regexr
    [Dart] Dynamic variable in Dart
    [NgRx] NgRx Runtime Checks
    [NgRx] Setting up NgRx Router Store and the Time-Travelling Debugger
    浅析数据库设计三范式
    建议别买三星Gear:半电脑产品 设计糟糕
    持续集成理论和实践的新进展
  • 原文地址:https://www.cnblogs.com/mc67/p/4801422.html
Copyright © 2011-2022 走看看