1. 程式人生 > >通過計算樣式封裝動畫例項—多條動畫結合,多個引數變化的動畫

通過計算樣式封裝動畫例項—多條動畫結合,多個引數變化的動畫

要點:

1.原來想寫animate()的多型形式的,寫到一半想起來,js不需要在宣告變數時就宣告資料型別,無法完成多型的性質,可以通過曲線方法完成多型效果,以後再說。

2.getComputerStyle計算樣式屬性,可以將setoff系列沒能獲取到的樣式屬性獲取出來,getComputerStyle能返回所呼叫物件的所有樣式鍵值對,形成一個樣式物件

3.這個例子中有原來可以改變一個引數,到後面通過物件改變多個引數,理解物件即為鍵值對的意義,同時理解var-in遍歷物件的

程式碼:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	<style type="text/css">
		*{
			padding: 0;
			margin: 0;
		}
		input{
			margin-top: 20px;
		}
		div{
			margin-top: 30px;
			width: 225px;
			height: 175px;
			background-color: #6D1F9B;
			position: absolute;
			/*一定要是相對定位,不然寫的移動的位置不能改變而顯示出來*/
		}
	</style>
</head>
<body>
	<input type="button" value="移動!" id="btn1">
	<input type="button" value="變變變" id="btn2">

	<div id="div"></div>


	<script type="text/javascript">
        function myGet(id){
        	return document.getElementById(id);
        }

        myGet("btn1").onclick = function(){
        	animate2(myGet("div"),"top",500);
        }
        myGet("btn2").onclick = function(){
        	animate(myGet("div"),{"top":200,"width":500,"height":500,"left":500,"opacity":0.3},function(){
        		animate(myGet("div"),{"top":100,"width":200,"height":200,"left":100,"opacity":0.9})});
        }


		function getStyle(element,attr){
			return window.getComputedStyle ? window.getComputedStyle(element,null)[attr]
			: element.currentStyle[attr];
			// 將原來的if-else語句進行判斷也相容程式碼的方式,進行簡化,寫成三目運算子的方式
			// 屬性後面的[attr]是跟點語法的作用是一樣的,但是這裡不能使用點語法獲取attr的物件屬性,因為attr是變數只有用[]接收不同型別字串
			// 獲取的計算後的樣式都是帶有單位的
		}

	    function animate2(element,attr,target){
        	clearInterval(element.intervalName);
        	// 每次點選移動按鈕的時候,清理定時器,將原來的定時器清理掉,不然會疊加多執行緒多個定時器,加快速度
        	element.intervalName = setInterval(function(){

	            var current = parseInt(getStyle(element,attr));
	            // 通過getStyle()獲取的是帶有單位的屬性值,通過parseInt轉換成值型別,不用number()是因為轉換過後的可能是nun
	            
	            var step = 80;
	            // 每次增加80畫素
	            step = current<target?step:-step;
	            // 判斷是在目標的左邊還是右邊,從而判斷是前進還是後退
	            current += step;	
	            if(Math.abs(target-current)>Math.abs(step)){
	            	element.style[attr] = current + "px";
	            }else{
	            	clearInterval(element.intervalName);
	            	element.style[attr] = target + "px";
	            	// 當執行到最後一步時,如果不滿增加的長度,而再一次執行時,而又超過目標畫素的距離,
	                // 所以設定直接一步到目標距離,而不會
	            }  	
            },300)
        }

        function animate(element,json,fn){
        	clearInterval(element.intervalName);
        	// 清理定時器

        	element,intervalName = setInterval(function(){
                var flag = true;
                // 哈哈哈,又是這個,因為遍歷for迴圈遍歷有先後順序,要都到達指定位置才能清理計時器

        		for(var attr in json){
                    if(attr == "zIndex"){
                    	// css中的屬性中間是連字元的屬性,在js操作中,將下劃線去掉同駝峰原則
                        // 層級的操作,直接賦值即可不需要其他的操作
                        element.style[attr] = json[attr];
                    }else if(attr == "opacity"){

                    	var current = getStyle(element,attr)*100;
	        			var target = json[attr]*100;
	        			// 將attr對應的值獲取到,直接通過物件的鍵值獲取,這個引數沒有單位直接獲取值
	        			var step = (target - current)/10;
	        			step = step>0 ? Math.ceil(step) : Math.floor(step);
	        			current += step;
	        			element.style[attr] = current/100;
	        			// 透明度不需要其他的引數,前面放大100倍,變回來
                    }else{
	    
	        			// 其他不同的屬性
                        // 遍歷json陣列物件,每次將遍歷的陣列物件屬性進行設定
	        			var current = parseInt(getStyle(element,attr));
	        			var target = json[attr];
	        			// 將attr對應的值獲取到,直接通過物件的鍵值獲取
	        			var step = (target - current)/10;
	        			// 將從當前位置到目標距離走十分之一
	        			step = step>0 ? Math.ceil(step) : Math.floor(step);
	        			// Math.ceil()和Math.floor()分別是向上和向下取整
	        			current += step;
	        			element.style[attr] = current + "px";
                    }

        			if(current != target){
                      flag = false;
                      // 也是類似於多執行緒,只有每個都為true才能到達指定位置
        			}
        		}   
        		    if(flag){
        		    	clearInterval(intervalName); 
        		    	// 所有的動畫執行完成之後,可以再執行一個函式
        		    	if(fn){
        		    		fn();
        		    	}
                        // 這裡呼叫的函式,也可以是本身這個函式,還可以 進行多次動畫
        		    }
        		    
        	},300)
        }
	</script>
</body>
</html>

 效果: