一個封裝函數的實現過程


目標:封裝一個函數,調用這個函數可以使任意的元素左右移動到任意的位置

1.准備工作

新知識點:用元素.style.屬性只能獲取標簽內用style = "屬性名:屬性值;"里設置的屬性,不能獲取在頭部的style標簽中設置的屬性

用DOM元素的一個方法可以獲取任意方式設置的屬性:對象.offsetLeft可以獲取left屬性值,其他的還有element.offsetTop、element.offsetHeight、element.offsetWidth等,這個案例中使用element.offsetLeft獲取盒子的向右偏移量,注意別忘了設置目標元素的position

CSS部分

<style>
     *{
         margin: 0;
         padding: 0;    
     }
        #dv{
            width: 100px;
            height: 100px;
            margin-top: 10px;
            background-color: pink;
            position: absolute;    
        }
    </style>

HTML部分

<input type="button" value="移動到400" id="btn1">
    <input type="button" value="移動到800" id="btn2">
    <div id="dv"></div>

2.利用事件函數實現最基礎的移動-版本1

<script>
    var btn1 = document.getElementById("btn1");
    var btn2 = document.getElementById("btn2");
    var dv = document.getElementById("dv");

    function f1(){        //第一個的事件函數
                var current = dv.offsetLeft;
                setInterval(function(){
                    if (current < 400) {
                        current += 10;
                        dv.style.left = current +"px";
                    }    
                },10);
            }

            function f2(){        //第二個的事件函數
                var current = dv.offsetLeft;
                setInterval(function(){
                    if (current < 800) {
                        current += 10;
                        dv.style.left = current +"px";
                    }    
                },10);
            }


    btn1.addEventListener("click",function(){f1();},false);
    btn2.addEventListener("click",function(){f2();},false);

    </script>

觀察f1,f2,只有內部if里的參數不同,可以引入目標位值參數將f1,f2變為一個函數
如何實現往回走呢?
關鍵在於if里的東西:判斷當前位置和目標位置的關系,當前位置<目標位值則要位置往前,當前位置>目標位值,則要位置往后

3.修改后的版本2-可以實現來回移動

   <script>
    var btn1 = document.getElementById("btn1");
    var btn2 = document.getElementById("btn2");
    var dv = document.getElementById("dv");
    function ff(target){
                var current = dv.offsetLeft;
                
                var timeId = setInterval(function(){
                    // if (current < target) {      //正走
                    //  current += 10;
                    //  dv.style.left = current +"px";  
                    // }else if(current > target){
                    //  current -= 10;      //反走
                    //  dv.style.left = current +"px"; 
                    // }else{
                    //  clearInterval(timeId);  //到達目的地清理定時器
                    // }    
                    //優化上述代碼如下,添加一個變量temp可以設置每次走得距離
                    
                    if (current != target) {
                        var temp = 10;  //設置每次走的距離  這句代碼放進計時器中才能實現往回走,即current>target的情況。因為這種情況每次計時都要設置temp = -10,不放進來的話temp會10,-10來回變,導致盒子抖動不能到達目標地
                    temp = current <= target ? temp : -temp;    
                        current += temp;
                        dv.style.left = current + "px";
                    }   
                    else{   //到達目的地清理定時器
                        clearInterval(timeId);
                    }
                },10);
    }

    btn1.addEventListener("click",function(){ff(400);},false);
    btn2.addEventListener("click",function(){ff(800);},false);

    </script>

注意應及時清理定時器以釋放內存空間和避免造成其他BUG。優化代碼引入了一個新的變量,這個變量的值甚至也可以由用戶指定(在形參列表中多加一個形參),每次走得距離和定時器的間隔共同形成了一幀一幀的畫面,實現了動畫移動的效果。

版本2出現BUG:如果設置的每次走得距離不能被400/800整除的話,會出現無法到達目的地而來回抖動的情況,而且無法實現清理定時器,在點擊下一個按鈕時會有多個定時器事件疊加發生,情況更復雜如:

    <script>
    var btn1 = document.getElementById("btn1");
    var btn2 = document.getElementById("btn2");
    var dv = document.getElementById("dv");
    function ff(target){
           var current = dv.offsetLeft;
                
                var timeId = setInterval(function(){
                    if (current != target) {
                        var temp = 90;  //設置每次走的距離  這里為了節約時間設置成了較大的距離
                    temp = current <= target ? temp : -temp;    
                        current += temp;
                        dv.style.left = current + "px";
                    }   
                    else{   //到達目的地清理定時器
                        clearInterval(tiemId);
                    }
                },1000);    //這里為了方便分析將間隔變大以看出每次定時器觸發后的結果,當然也可以利用控制台設置斷點分析
    }

    btn1.addEventListener("click",function(){ff(400);},false);
    btn2.addEventListener("click",function(){ff(800);},false);

    </script>

 

4.版本3:解決上述BUG

 <script>
    var btn1 = document.getElementById("btn1");
    var btn2 = document.getElementById("btn2");
    var dv = document.getElementById("dv");
    function ff(target){
                clearInterval(timeId);  //解決隱藏的BUG,每次點擊先清理定時器再創建定時器,解決多次點擊時運動變快的BUG
                var current = dv.offsetLeft;
                var timeId = setInterval(function(){
                    if (current != target) {
                        var temp = 9;   //設置每次走的距離  
                        temp = current <= target ? temp : -temp;
                        if (Math.abs(current-target) > Math.abs(temp)) {    //當前距離大於每次走得距離則繼續走
                            current += temp;
                            dv.style.left = current + "px";
                        } else {        //當前距離小於等於每次走得距離:則直接跳到目標位置,並且清理定時器
                            dv.style.left = target + "px";
                            clearInterval(timeId);
                        }   
                    }   
                    
                },10);
            }

    btn1.addEventListener("click",function(){ff(400);},false);
    btn2.addEventListener("click",function(){ff(800);},false);

    </script>

5.版本4最終版本,如果將目標元素作為函數的參數,則實現操縱任意元素的目的,注意要給目標元素添加position

function move(element,target){
            clearInterval(timeId);    //解決隱藏的BUG,每次點擊先清理定時器再創建定時器,解決多次點擊時運動變快的BUG
            var current = element.offsetLeft;
            var timeId = setInterval(function(){
                if (current != target) {
                    var temp = 9;    //設置每次走的距離    這句代碼放進計時器中才能實現往回走,即current>target的情況。因為這種情況每次計時都要設置temp = -10,不放進來的話temp會10,-10來回變,導致盒子抖動不能到達目標地
                    temp = current <= target ? temp : -temp;
                    if (Math.abs(current-target) > Math.abs(temp)) {    //當前距離大於每次走得距離則繼續走
                        current += temp;
                        element.style.left = current + "px";
                    } else {        //當前距離小於等於每次走得距離:則直接跳到目標位置,並且清理定時器
                        element.style.left = target + "px";
                        clearInterval(timeId);
                    }    
                }    
                
            },10);
        }

        btn1.addEventListener("click",function(){move(dv,400);},false);
        btn2.addEventListener("click",function(){move(dv,800);},false);

 

通過封裝一個函數,得到很多啟發,封裝函數-完成同一類事件可以多次調用--哪些東西需要作為參數傳入-如何一步步實現目的-如何分析BUG解決BUG-如何優化函數

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM