勻速運動 (當需要物體做勻速運動直接調用statMove函數) 緩衝運動(越接近目標,速度越慢) 緩運運動比直線運動視覺性更好,所以很常用 1 function startMove(dom, targetPosetion) { 2 clearInterval(timer); 3 var speed ...
勻速運動 (當需要物體做勻速運動直接調用statMove函數)
1 function startMove(dom,targetPosetion){ //dom : 運動對象,targetPosition : 到達目標位置 2 clearInterval(timer); // 防止定時器疊加,先清除定時器。 3 var speed = targetPosetion - dom.offsetLeft > 0 ? 7 : -7; 4 //斷物體到移動的目標位置的左邊還是右邊,左邊速度是正的,右邊速度是負的。 5 timer = setInterval(function(){ //設置定時器。變數timer要定義在函數外面。 6 if(Math.abs(targetPosetion - dom.offsetLeft ) < Math.abs(speed)){ 7 clearInterval(timer); 8 //當目位置減去物體偏移量小於定時器移動的位置(因為在移動就超出了目標位置),清除定時器 9 dom.style.left = targetPosetion + "px"; 10 //因為距離目標位置還有一小段距離,直接讓物體等於目標位置就行 11 }else{ 12 dom.style.left = dom.offsetLeft + speed + "px"; 13 } 14 },30); 15 }緩衝運動(越接近目標,速度越慢) 緩運運動比直線運動視覺性更好,所以很常用
1 function startMove(dom, targetPosetion) { 2 clearInterval(timer); 3 var speed = null; 4 timer = setInterval(function () { //設置定時器。變數timer要定義在函數外面。 5 speed = (targetPosetion - dom.offsetLeft) /10; 6 speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed); 7 if(dom.offsetLeft == targetPosetion){ 8 clearInterval(timer); 9 }else{ 10 dom.style.left = dom.offsetLeft + speed + "px"; 11 } 12 }, 30) 13 }5: 目標位置 - 物體偏移量(因為目標位置固定的,但是物體偏移量越來越大,所以會越來越慢)第10行的dom.offsetLeft和第5行負的dom.offsetLeft互相抵消掉了,dom.style.left直接等於目標位置(速度太大),所以要除以一個小數。 6:當目標位置 - 物體偏移量小於除數時,speed就等於小數了, 但是偏移量都是整數,就會自動的取捨值,例如:dom.style.left = 35.6px 實際會轉換成dom.style.left = 36px;所以只要有小數就向上取整(Math.ceil()),加上1。當是負值的時候就下取整(Math.floor()).因為當speed是小數時,就會被取整。所以最後是一個像素一個像素加上去的,所以物體的偏移量正好等於目標位置時就清除定時器。 顏色漸變的緩衝運動 因為讓當前的顏色漸變需要讓當前的opacity增加或減少,獲取當前的透明度opacity可以用計算樣式window.getComputedStyle。 計算樣式只讀,返回的都是絕對值,沒有相對單位
1 function getStyle(dom,attr){ 2 if(window.getComputedStyle){ 3 return window.getComputedStyle(dom,null)[attr]; 4 } 5 else{ 6 return dom.currentStyle[attr]; //IE8不相容,IE獨有屬性currentStyle 7 } 8 }讓物體透明度緩衝變化
1 startMove(div,25); 2 function startMove(dom, targetPosetion) { 3 clearInterval(timer); 4 var speed = null,current = null; 5 timer = setInterval(function () { 6 current = parseFloat(getStyle(div,'opacity')) * 100; 7 console.log(current); 8 speed = (targetPosetion - current) / 10; 9 speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed); 10 if (current == targetPosetion) { 11 clearInterval(timer); 12 } else { 13 dom.style.opacity = (current + speed) / 100; 14 } 15 }, 30) 16 }
因為透明度的取值範圍是0-1,把緩衝範圍變大,調用函數時和獲取當前透明度值時擴大100倍,增大緩衝區間,當給opacity賦值的時候縮小100倍。 多物體運動 4個div,移入到那個div,寬度做緩衝運動移動到400;移除寬度變為100。 下麵的代碼。橙色的部分有timer變為dom自己的屬性dom.timer, 在上面定義timer的時候,定義的timer是在函數外面的,4個div共用一個timer定時器, 當移入一個div時,開啟一個定時器,移出div時,又把上一個定時器給清除了,重新開啟了一個定時器。 當從上一個div快速移入一個新的div時,還沒等回到100,開啟的那個新的div。就把上一個div給清除了。 所以解決這個問題,就是在每個div上都加一個定時器。 當清理定時器的時候也是清理自己的定時器,不會影響其他的,就在每個元素上加上timer屬性。 function startMove(dom, targetPosetion) {
clearInterval(dom.timer); var speed = null; dom.timer = setInterval(function () { current = parseFloat(getStyle(dom, 'width')); //用計算樣式獲取當前寬度值。 speed = (targetPosetion - current) / 10; speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed); console.log(speed, current); if (current == targetPosetion) { clearInterval(dom.timer); } else { dom.style.width = current + speed + "px"; } }, 30) } var div = document.getElementsByTagName('div'); for (var i = 0; i < div.length; i++) { div[i].onmouseenter = function () { startMove(this, 400) } div[i].onmouseleave = function(){ startMove(this,100); } } 多物體不同屬性運動
1 function startMove(dom , attr , target){ 2 clearInterval(dom.timer); 3 dom.timer = setInterval(function(){ 4 var current = null,speed = null; 5 if(attr == 'opacity'){ 6 current = parseFloat(getStyle(dom,attr)) * 100; 7 }else{ 8 current = parseFloat(getStyle(dom,attr)); 9 } 10 speed = (target - current) / 10; 11 speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed); 12 if(current == target){ 13 clearInterval(dom.timer); 14 } 15 if(attr == 'opacity'){ 16 dom.style.opacity = (current + speed) / 100; 17 }else{ 18 dom.style[attr] = (current + speed) + "px"; 19 } 20 },30) 21 } 22 23 var div = document.getElementsByTagName('div'); 24 div[0].onmouseenter = function(){ 25 startMove(this,'width',400); 26 }; 27 div[1].onmouseenter = function(){ 28 startMove(this,'height',400); 29 }; 30 div[2].onmouseenter = function(){ 31 startMove(this,'borderWidth',20); 32 }; 33 div[3].onmouseenter = function(){ 34 startMove(this,'opacity',50); 35 };
多物體多值運動 + 回調機制
function startMove(dom, targetObj, callback) { clearInterval(dom.timer); dom.timer = setInterval(function () { var stop = true; var speed = null, current = null; for (var prop in targetObj) { if (prop == 'opacity') { current = parseFloat(getStyle(dom, prop))*100; } else { current = parseFloat(getStyle(dom, prop)); } speed = (targetObj[prop] - current) / 10; speed = speed>0?Math.ceil(speed):Math.floor(speed); if (prop == 'opacity') { dom.style.opacity = (current + speed) / 100; } else { dom.style[prop] = (current + speed) + "px"; } if (targetObj[prop] != current) { stop = false; } } if (stop == true) { clearInterval(dom.timer); typeof callback == 'function' && callback(); } }, 30); }
//讓多物體多值運動,由於多值就可以用對象來裝。
startMove(dom, targetObj, callback)接收3個參數,運動對象,想要改變的多值屬性對象,回調函數
跟上面一樣一地步清除定時器,然後設置定時器,用for in 迴圈傳過來的對象屬性,
如果傳過來的是opacity 就要擴大100倍,不是就正常調用上面getStyle()方法,返回一個計算屬性。
設置一個鎖,每次定時器執行時定義一個變數stop = true 可以停止,
當for in 迴圈時,判斷如果有一個當前值不等於目標值的時候,就讓stop = false。不可以停止
for in 結束,stop == true 的時候就代表所有的值都到達目標值,這時候就可以清空定時器。這個運動過程結束,調用回調函數
1 var divOne = document.getElementById('one'); 2 var divTwo = document.getElementById('two'); 3 divOne.onclick = function () { 4 startMove(this, { width: 400,height: 400,left: 200,top: 300,opacity: 50}, function () { 5 startMove(divTwo, { width: 400, height: 400, left: 200, top: 300, opacity: 50 }, function () { 6 alert(555); 7 }) 8 }) 9 }