目標:封裝一個函數,調用這個函數可使任意的元素左右移動到任意的位置函數
1.準備工做優化
新知識點:用元素.style.屬性只能獲取標籤內用style = "屬性名:屬性值;"裏設置的屬性,不能獲取在頭部的style標籤中設置的屬性動畫
用DOM元素的一個方法能夠獲取任意方式設置的屬性:對象.offsetLeft能夠獲取left屬性值,其餘的還有element.offsetTop、element.offsetHeight、element.offsetWidth等,這個案例中使用element.offsetLeft獲取盒子的向右偏移量,注意別忘了設置目標元素的positionspa
CSS部分code
<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.利用事件函數實現最基礎的移動-版本1blog
<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-能夠實現來回移動ip
<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-如何優化函數