動畫效果在網站中是一種非常常見的互動式體驗效果,比如側邊欄分享、圖片淡入淡出,我們把這種動畫效果就叫做運動,也就是讓物體動起來。如果想讓一個物體動起來,無非就是改變它的速度,也就是改變屬性值,比如 left、right、width、height、opacity ,那麼既然是運動,就可以分為很多種.....
動畫效果在網站中是一種非常常見的互動式體驗效果,比如側邊欄分享、圖片淡入淡出,我們把這種動畫效果就叫做運動,也就是讓物體動起來。如果想讓一個物體動起來,無非就是改變它的速度,也就是改變屬性值,比如 left、right、width、height、opacity ,那麼既然是運動,就可以分為很多種,如勻速運動、緩衝運動、多物體運動、任意值運動、鏈式運動和同時運動。我們從最簡單的動畫開始,如何讓單個物體運動,逐步深入多物體運動、多動畫同時運動到實現完美運動框架的封裝,在這個過程中,每一個運動都封裝為一個函數,可以更好的培養和鍛煉我們的編程思想,增強邏輯思維。
1、簡單運動
簡單運動的實現都是勻速運動,顧名思義就是運動速度不變,通過寬、高、透明度等的變化,實現簡單的動畫效果,下麵我們就讓一個 div 運動起來。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>簡單運動</title> 6 <style> 7 *{margin:0;padding:0;} 8 #div1{ 9 width:200px; 10 height:200px; 11 background:green; 12 position:absolute; 13 } 14 </style> 15 <script> 16 function startMove(){ 17 var oDiv = document.getElementById('div1'); 18 setInterval(function (){ 19 oDiv.style.left = oDiv.offsetLeft + 10 + 'px'; 20 },30); 21 } 22 </script> 23 </head> 24 <body> 25 <input type="button" value="動起來" onclick="startMove()"> 26 <div id="div1"></div> 27 </body> 28 </html>
讓一個 div 動起來,只需要開一個定時器,用於定義速度,告訴物體運動的快慢,上面的代碼,當點擊按鈕後,div 每隔30毫秒從左向右運動10像素。
這裡需要註意,讓 div 向右運動,在定義樣式時,一定要給運動的物體加絕對定位,也就是相對於哪個位置進行運動,offsetLeft 代表物體的當前位置,所以每次運動,都是給當前的 offsetLeft 加10像素。
雖然是讓 div 動起來了,但是問題多多,動起來後根本停不下來,這樣就太任性了,而且當重覆點擊的話,運動速度還會加快,這都不是我們想要的,下麵就我們就讓他停止在指定位置處。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>簡單運動</title> 6 <style> 7 *{margin:0;padding:0;} 8 #div1{ 9 width:200px; 10 height:200px; 11 background:green; 12 position:absolute; 13 } 14 </style> 15 <script> 16 var timer = null; 17 function startMove(){ 18 var oDiv = document.getElementById('div1'); 19 clearInterval(timer); 20 timer = setInterval(function (){ 21 if(oDiv.offsetLeft == 300){ 22 clearInterval(timer); 23 } 24 else{ 25 oDiv.style.left = oDiv.offsetLeft + 10 + 'px'; 26 } 27 },30); 28 } 29 </script> 30 </head> 31 <body> 32 <input type="button" value="動起來" onclick="startMove()"> 33 <div id="div1"></div> 34 </body> 35 </html>
上面的代碼,點擊按鈕後,div 從左向右運動到300像素時停止運動。
若要停止一個物體的運動,只要關閉定時器即可,也就是判斷 div 的 offsetLeft 值是否等於300,若等於300則清空定時器。這裡需要註意,在做判斷時,一定要給運動位置加 else,判斷語句為二選一,成立或者不成立時執行,這樣再點擊按鈕就不會運動了,否則當 div 運動到300像素時,再點擊按鈕,div 還會向右移動10像素,雖然在到達300像素時已經關閉了定時器,但是按鈕的點擊事件,還會執行一次函數,所以加了 else 之後,當再點擊按鈕時,這時候條件已經成立了,也就不會再執行 else 中的語句了。
重覆點擊按鈕,運動速度會不斷加快,是因為每點擊一次按鈕,startMove 函數被執行一次,多次點擊,也就相當於開了多個定時器,所以需要在執行 startMove 函數時,首先清空定時器,這樣重覆點擊按鈕時,會先把之前運行的定時器關閉,再開一個新的定時器運行,這就保證了始終是一個定時器在工作。
下麵我們看兩個簡單動畫的實例:
實例:側邊欄分享
實現思路:網站側邊欄菜單是最常見的動畫效果,該效果在初始時,只顯示一個按鈕或者菜單項,當滑鼠移上去時,滑出隱藏部分,展示內容。該效果在做佈局時,主要用絕對定位實現隱藏,left 的值為內容容器 width 的值,該值為負值,動畫效果實現就是改變它的 offsetLeft 的值,當滑鼠移入時,增加 offsetLeft 的值,值為0時停止運動,當滑鼠移開時,offsetLeft 的值從0減小到 left 的值。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>側邊欄分享</title> 6 <style> 7 *{margin:0;padding:0;} 8 #div1{ 9 width:150px; 10 height:210px; 11 background:lightgreen; 12 position:absolute; 13 left:-150px; 14 } 15 #div1 span{ 16 width:20px; 17 height:60px; 18 line-height:20px; 19 color:white; 20 background:green; 21 position:absolute; 22 right:-20px; 23 top:70px; 24 } 25 </style> 26 <script> 27 window.onload = function (){ 28 var oDiv = document.getElementById('div1'); 29 oDiv.onmouseover = function (){ 30 startMove(); 31 }; 32 oDiv.onmouseout = function (){ 33 stopMove(); 34 }; 35 }; 36 var timer = null; 37 function startMove(){ 38 var oDiv = document.getElementById('div1'); 39 clearInterval(timer); 40 timer = setInterval(function (){ 41 if(oDiv.offsetLeft == 0){ 42 clearInterval(timer); 43 } 44 else{ 45 oDiv.style.left = oDiv.offsetLeft + 10 + 'px'; 46 } 47 },30); 48 } 49 function stopMove(){ 50 var oDiv = document.getElementById('div1'); 51 clearInterval(timer); 52 timer = setInterval(function (){ 53 if(oDiv.offsetLeft == -150){ 54 clearInterval(timer); 55 } 56 else{ 57 oDiv.style.left = oDiv.offsetLeft - 10+ 'px'; 58 } 59 },30); 60 } 61 </script> 62 </head> 63 <body> 64 <div id="div1"> 65 <span>分享到</span> 66 </div> 67 </body> 68 </html>
上面的代碼,當滑鼠移入"分享到",隱藏的 div 即內容容器每隔30毫秒從左向右運動10像素,offsetLeft 值為0時停止運動,當滑鼠移開時,顯示的 div 每隔30毫秒從右向左移動5像素,offsetLeft 值為-150時停止運動。這裡要註意的是,offsetLeft 值的變化,從左向右運動時,值為正值,也就是+10,從右向左運動時,值為負值,也就是-10。
我們可以看到,startMove 和 stopMove 都有相同的代碼結構,如果代碼中存在大致相同的代碼,就可以對代碼進行優化,上面的代碼,就只有 offsetLeft 的移動位置 和 停止位置不同,因此可以用函數傳參的方式將上面的代碼簡化為:
1 <script> 2 window.onload = function (){ 3 var oDiv = document.getElementById('div1'); 4 oDiv.onmouseover = function (){ 5 startMove(10, 0); 6 }; 7 oDiv.onmouseout = function (){ 8 startMove(-10, -150); 9 }; 10 }; 11 var timer = null; 12 function startMove(speed, iTarget){ 13 var oDiv = document.getElementById('div1'); 14 clearInterval(timer); 15 timer = setInterval(function (){ 16 if(oDiv.offsetLeft === iTarget){ 17 clearInterval(timer); 18 } 19 else{ 20 oDiv.style.left = oDiv.offsetLeft + speed + 'px'; 21 } 22 },30); 23 } 24 </script>
移動位置也就是速度,用 speed 參數傳入,停止位置也就是目標位置,用 iTarget 參數傳入。在功能相同的情況下,一個函數傳入的參數越少越好,那麼還可以簡化為:
1 <script> 2 window.onload = function (){ 3 var oDiv = document.getElementById('div1'); 4 oDiv.onmouseover = function (){ 5 startMove(0); 6 }; 7 oDiv.onmouseout = function (){ 8 startMove(-150); 9 }; 10 }; 11 var timer = null; 12 function startMove(iTarget){ 13 var oDiv = document.getElementById('div1'); 14 clearInterval(timer); 15 timer = setInterval(function (){ 16 var speed = 0; 17 if(oDiv.offsetLeft > iTarget){ 18 speed = -10; 19 } 20 else{ 21 speed = 10; 22 } 23 if(oDiv.offsetLeft == iTarget){ 24 clearInterval(timer); 25 } 26 else{ 27 oDiv.style.left = oDiv.offsetLeft + speed + 'px'; 28 } 29 },30); 30 } 31 </script>
速度值和目標值,目標值肯定是不能省略的,就好比坐火車,買票肯定得有一個終點,所以速度值可以被省略掉,不管是動車還是普通車,都會到達終點,不同的就是速度的快慢。首先讓速度值等於0,再做一個判斷,判斷目標值與物體當前位置的關係,如果 offsetLeft 值大於目標值,那麼就要從右向左運動,所以為負值,否則,也就是目標值大於 offsetLeft 值,這說明此時物體是隱藏的,那麼就從左向右運動,速度值為正值。
該效果如果用緩衝運動做的話,效果更好。
實例:淡入淡出
淡入淡出效果是滑鼠移入移出改變透明度,透明度動畫也屬於運動效果,可以使用上例中 startMove 框架完成這種效果。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>淡入淡出</title> 6 <style> 7 #div1{ 8 width:200px; 9 height:200px; 10 background:red; 11 filter:alpha(opacity:30); 12 opacity:0.3; 13 } 14 </style> 15 <script> 16 window.onload = function (){ 17 var oDiv = document.getElementById('div1'); 18 oDiv.onmouseover = function (){ 19 startMove(100); 20 }; 21 oDiv.onmouseout = function (){ 22 startMove(30); 23 }; 24 }; 25 var alpha = 30; //將透明度值存儲在變數中 26 var timer = null; 27 function startMove(iTarget){ 28 var oDiv = document.getElementById('div1'); 29 clearInterval(timer); 30 timer = setInterval(