1. 入門案例——實現勻速運動
2. 入門案例——實現緩衝運動
3. 實現任意值的運動框架v.1
4. 改進任意值的運動框架v.2
5. 改進任意值的運動框架v.3
6. 實現鏈式運動框架
7. 實現完美運動框架
二、內容
1. 入門案例——實現勻速運動
①. 要求:只要簡單的實現傳入的對象和運動的最終目標,便能操作該對象的left屬性的大小勻速的變化到目標大小。
②. 具體代碼:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title></title> 6 <style> 7 #div1 { 8 width: 100px; 9 height: 100px; 10 background: red; 11 margin: 10px; 12 position:absolute; 13 } 14 </style> 15 <script> 16 var timer = null; //定時器 17 var speed = 10; //運動速度 18 function uniformMotion(obj,iTarget) { 19 if (obj.offsetLeft > iTarget) { //判斷當前left屬性的值與最終目標的值之間的位置 20 speed = -10; //說明當前對象的位置在目標值的右邊 21 } else { 22 speed = 10; 23 } 24 clearInterval(timer); //先關閉之前的定時器 25 timer = setInterval(function () { //開啓定時器,並保存返回的定時器對象 26 if (obj.offsetLeft == iTarget) { 27 clearInterval(timer); //運動到目標後關閉定時器 28 } else if (Math.abs(obj.offsetLeft - iTarget) < Math.abs(speed)) { 29 obj.style.left = iTarget + 'px'; //如果當前位置與目標的位置不足10,那麼就讓它直接跳到目標位置上 30 clearInterval(timer); //關閉定時器 31 } else { 32 obj.style.left = obj.offsetLeft + speed + 'px'; //讓當前位置向目標位置移動 33 } 34 }, 30); 35 } 36 window.onload = function () { 37 var btn = document.getElementsByTagName("input")[0]; 38 var oDiv = document.getElementById("div1"); 39 btn.onclick = function(){ 40 uniformMotion(oDiv,300); 41 } 42 } 43 </script> 44 </head> 45 <body> 46 <input type="button" value="勻速運動"/> 47 <div id="div1"></div> 48 </body> 49 </html>
2. 入門案例——實現緩衝運動
①. 要求:只要簡單的實現傳入的對象和運動的最終目標,便能操作該對象的left屬性的大小由大到小的變化到目標大小。
②. 具體代碼:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title></title> 6 7 <style> 8 div { 9 width: 100px; 10 height: 100px; 11 position: absolute; 12 background: red; 13 margin: 10px; 14 left: 100px; 15 } 16 17 #div2{ 18 width: 1px; 19 height:300px; 20 background-color: black; 21 position: absolute; 22 left:600px; 23 } 24 </style> 25 <script> 26 /*緩衝運動*/ 27 var timer = null; 28 var speed = 0; 29 function UnUniformModition(obj,iTarget) { 30 clearInterval(timer); 31 timer = setInterval(function () { 32 if (parseInt(getStyle(obj, "left")) == iTarget) { 33 clearInterval(timer); 34 } else { 35 speed = (iTarget - parseInt(getStyle(obj, "left"))) / 10; 36 speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed); 37 obj.style.left = parseInt(getStyle(obj, "left")) + speed + "px"; 38 } 39 }, 30); 40 } 41 /* 用來獲取樣式的值 obj-對象,name-樣式名*/ 42 function getStyle(obj, name) { 43 if (obj.currentStyle) { 44 return obj.currentStyle[name]; 45 } else { 46 return getComputedStyle(obj, false)[name]; 47 } 48 } 49 window.onload = function () { 50 var btn = document.getElementsByTagName("input")[0]; 51 var oDiv = document.getElementsByTagName("div")[0]; 52 btn.onclick = function () { 53 UnUniformModition(oDiv,600); 54 } 55 } 56 </script> 57 </head> 58 <body> 59 <input type="button" value="緩衝運動"> 60 <div></div> 61 <div id="div2"></div> 62 </body> 63 </html>
3. 實現任意值的運動框架v.1
①. 要求:只要簡單的實現傳入的對象、要變化的屬性名和運動的最終目標,便能操作該對象的傳入要變花屬性的值由大到小的變化到目標大小。(基於緩衝運動)
②. 具體代碼:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>任意值運動框架version 1.0</title> 6 <style> 7 div { 8 width: 100px; 9 height: 100px; 10 background: green; 11 margin: 10px; 12 } 13 #div2 { 14 border: 1px solid black; 15 } 16 #div3{ 17 -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=30); 18 filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=30); 19 opacity: 0.3; 20 } 21 </style> 22 <script> 23 /** 24 * 25 * @param obj 操作對象 26 * @param attr 屬性名 27 * @param iTarget 目標值 28 */ 29 var timer = null; 30 function startMove(obj, attr, iTarget) { 31 clearInterval(timer); 32 timer = setInterval(function () { 33 var cur = 0; 34 if (attr == 'opacity') { //單獨處理透明度問題,因爲只有透明度一定要小數 35 cur = parseFloat(getStyle(obj, attr)) * 100;//乘以100是讓透明度的0~1之間的度數擴大,方便後面的使用 36 } else { 37 cur = parseInt(getStyle(obj, attr)); 38 } 39 var speed = (iTarget - cur) / 6; //讓速度與當前位置離ITarget的距離成正比。除數越大那麼緩衝就越大 40 speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed); 41 if (cur == iTarget) { 42 clearInterval(timer); 43 } else { 44 if (attr == 'opacity') { 45 obj.style.filter = 'alpha(opacity:' + (cur + speed) + ')'; 46 obj.style.opacity = (cur + speed) / 100;//把範圍重新縮小爲0~1之間 47 } else { 48 obj.style[attr] = cur + speed + 'px'; 49 } 50 } 51 }, 30); 52 } 53 /** 54 * 獲取樣式屬性的值。代替offset。 55 * @param obj 操作對象 56 * @param name 屬性名 57 * @returns {*} 58 */ 59 function getStyle(obj, name) { 60 if (obj.currentStyle) { 61 return obj.currentStyle[name]; 62 } else { 63 return getComputedStyle(obj, false)[name]; 64 } 65 } 66 67 /** 68 * 測試: 69 * 下面的例子只能一個一個進行測試,因爲在這裏沒有設置多對象動作, 70 * 也就是說定時器此時是共有的,如果同時使用這個定時器,會出錯。 71 */ 72 window.onload = function () { 73 //測試width的變化(未設置border等其他影響width的屬性) 74 var oDiv1 = document.getElementById("div1"); 75 oDiv1.onmouseover = function () { 76 startMove(this, "width", 500); 77 } 78 oDiv1.onmouseout = function () { 79 startMove(this, "width", 100); 80 } 81 //測試width的變化(設置了影響width值得元素) 82 /* 83 var oDiv2 = document.getElementById("div2"); 84 oDiv2.onmouseover = function () { 85 startMove(this, "width", 500); 86 } 87 oDiv2.onmouseout = function () { 88 startMove(this, "width", 100); 89 } 90 */ 91 92 //測試width的變化(設置了影響width值得元素) 93 /* 94 var oDiv3 = document.getElementById("div3"); 95 oDiv3.onmouseover = function () { 96 startMove(this, "opacity", 100); 97 } 98 oDiv3.onmouseout = function () { 99 startMove(this, "opacity", 30); 100 } 101 */ 102 } 103 </script> 104 </head> 105 <body> 106 <div id="div1"></div> 107 <div id="div2"></div> 108 <div id="div3"></div> 109 </body> 110 </html>
4. 改進任意值的運動框架v.2
①. 要求:在ie低版本測試下,透明度的值因爲是小數,會出現一些特殊的情況,所以對此進行改進。
②. 具體代碼:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <!-- 2.o版本對透明度的算法進行了改進,加進了round方法 具體內容在39行--> 5 <meta charset="UTF-8"> 6 <title>任意值運動框架version 2.0</title> 7 <style> 8 div { 9 width: 100px; 10 height: 100px; 11 background: green; 12 margin: 10px; 13 } 14 15 #div2 { 16 border: 1px solid black; 17 } 18 #div3{ 19 -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=30); 20 filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=30); 21 opacity: 0.3; 22 } 23 </style> 24 <script> 25 /** 26 * 27 * @param obj 操作對象 28 * @param attr 屬性名 29 * @param iTarget 目標值 30 */ 31 var timer = null; 32 function startMove(obj, attr, iTarget) { 33 clearInterval(timer); 34 timer = setInterval(function () { 35 var cur = 0; 36 if (attr == 'opacity') { //單獨處理透明度問題,因爲只有透明度一定要小數 37 //因爲parseFloat會得到一個帶小數的值,因爲計算機會有誤差,所以會得到一些奇怪的數值。 38 //因此在這裏使用round()方法對其值進行四捨五入,去除掉小數 39 cur = Math.round(parseFloat(getStyle(obj, attr)) * 100); 40 } else { 41 cur = parseInt(getStyle(obj, attr)); 42 } 43 var speed = (iTarget - cur) / 6; //讓速度與當前位置離ITarget的距離成正比。除數越大那麼緩衝就越大 44 //如果attr的值是0~1之間的話,下面這句代碼將不可用,如果是0~100之間的話,那麼就沒問題 45 speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed); 46 if (cur == iTarget) { 47 clearInterval(timer); 48 } else { 49 if (attr == 'opacity') { 50 obj.style.filter = 'alpha(opacity:' + (cur + speed) + ')'; 51 obj.style.opacity = (cur + speed) / 100;//把範圍重新縮小爲0~1之間 52 } else { 53 obj.style[attr] = cur + speed + 'px'; 54 } 55 } 56 }, 30); 57 } 58 /** 59 * 獲取樣式屬性的值。代替offset。 60 * @param obj 操作對象 61 * @param name 屬性名 62 * @returns {*} 63 */ 64 function getStyle(obj, name) { 65 if (obj.currentStyle) { 66 return obj.currentStyle[name]; 67 } else { 68 return getComputedStyle(obj, false)[name]; 69 } 70 } 71 72 /** 73 * 測試: 74 * 下面的例子只能一個一個進行測試,因爲在這裏沒有設置多對象動作, 75 * 也就是說定時器此時是共有的,如果同時使用這個定時器,會出錯。 76 */ 77 window.onload = function () { 78 //測試width的變化(未設置border等其他影響width的屬性) 79 var oDiv1 = document.getElementById("div1"); 80 oDiv1.onmouseover = function () { 81 startMove(this, "width", 500); 82 } 83 oDiv1.onmouseout = function () { 84 startMove(this, "width", 100); 85 } 86 //測試width的變化(設置了影響width值得元素) 87 /* 88 var oDiv2 = document.getElementById("div2"); 89 oDiv2.onmouseover = function () { 90 startMove(this, "width", 500); 91 } 92 oDiv2.onmouseout = function () { 93 startMove(this, "width", 100); 94 } 95 */ 96 97 //測試width的變化(設置了影響width值得元素) 98 /* 99 var oDiv3 = document.getElementById("div3"); 100 oDiv3.onmouseover = function () { 101 startMove(this, "opacity", 100); 102 } 103 oDiv3.onmouseout = function () { 104 startMove(this, "opacity", 30); 105 } 106 */ 107 } 108 </script> 109 </head> 110 <body> 111 <div id="div1"></div> 112 <div id="div2"></div> 113 <div id="div3"></div> 114 </body> 115 </html>
5. 改進任意值的運動框架v.3
①. 要求:在任意值的運動框架的1/2版本中,都沒有實現多物體運動,也就是同時多個物體進行運動,在第三版本中加入了多物體運動的功能。
②. 具體代碼:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <!-- 3.o版本 支持多物體運動 下面的三個例子可以同時測試--> 5 <meta charset="UTF-8"> 6 <title>任意值運動框架version 2.0</title> 7 <style> 8 div { 9 width: 100px; 10 height: 100px; 11 background: green; 12 margin: 10px; 13 } 14 15 #div2 { 16 border: 1px solid black; 17 } 18 #div3{ 19 -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=30); 20 filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=30); 21 opacity: 0.3; 22 } 23 </style> 24 <script> 25 26 27 /** 28 * 29 * @param obj 操作對象 30 * @param attr 屬性名 31 * @param iTarget 目標值 32 */ 33 function startMove(obj, attr, iTarget) { 34 clearInterval(obj.timer); 35 obj.timer = setInterval(function () { 36 var cur = 0; 37 if (attr == 'opacity') { //單獨處理透明度問題,因爲只有透明度一定要小數 38 //因爲parseFloat會得到一個帶小數的值,因爲計算機會有誤差,所以會得到一些奇怪的數值。 39 //因此在這裏使用round()方法對其值進行四捨五入,去除掉小數 40 cur = Math.round(parseFloat(getStyle(obj, attr)) * 100); 41 } else { 42 cur = parseInt(getStyle(obj, attr)); 43 } 44 var speed = (iTarget - cur) / 6; //讓速度與當前位置離ITarget的距離成正比。除數越大那麼緩衝就越大 45 //如果attr的值是0~1之間的話,下面這句代碼將不可用,如果是0~100之間的話,那麼就沒問題 46 speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed); 47 if (cur == iTarget) { 48 clearInterval(obj.timer); 49 } else { 50 if (attr == 'opacity') { 51 obj.style.filter = 'alpha(opacity:' + (cur + speed) + ')'; 52 obj.style.opacity = (cur + speed) / 100;//把範圍重新縮小爲0~1之間 53 } else { 54 obj.style[attr] = cur + speed + 'px'; 55 } 56 } 57 }, 30); 58 } 59 60 61 /** 62 * 獲取樣式屬性的值。代替offset。 63 * @param obj 操作對象 64 * @param name 屬性名 65 * @returns {*} 66 */ 67 function getStyle(obj, name) { 68 if (obj.currentStyle) { 69 return obj.currentStyle[name]; 70 } else { 71 return getComputedStyle(obj, false)[name]; 72 } 73 } 74 75 /** 76 * 測試: 77 * 下面的例子只能一個一個進行測試,因爲在這裏沒有設置多對象動作, 78 * 也就是說定時器此時是共有的,如果同時使用這個定時器,會出錯。 79 */ 80 window.onload = function () { 81 //測試width的變化(未設置border等其他影響width的屬性) 82 var oDiv1 = document.getElementById("div1"); 83 oDiv1.timer = null; 84 oDiv1.onmouseover = function () { 85 startMove(this, "width", 500); 86 } 87 oDiv1.onmouseout = function () { 88 startMove(this, "width", 100); 89 } 90 //測試width的變化(設置了影響width值得元素) 91 var oDiv2 = document.getElementById("div2"); 92 oDiv2.timer = null; 93 oDiv2.onmouseover = function () { 94 startMove(this, "width", 500); 95 } 96 oDiv2.onmouseout = function () { 97 startMove(this, "width", 100); 98 } 99 100 //測試opacity的變化 101 var oDiv3 = document.getElementById("div3"); 102 oDiv3.timer = null; 103 oDiv3.onmouseover = function () { 104 startMove(this, "opacity", 100); 105 } 106 oDiv3.onmouseout = function () { 107 startMove(this, "opacity", 30); 108 } 109 } 110 </script> 111 </head> 112 <body> 113 <div id="div1"></div> 114 <div id="div2"></div> 115 <div id="div3"></div> 116 </body> 117 </html>
6. 實現鏈式運動框架
①. 要求:讓其運動可以一個接一個的運行,也就是鏈式運動。具體效果看測試代碼
②. 具體代碼:
html代碼部分:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title></title> 6 <style> 7 #div1{ 8 width:100px; 9 height:100px; 10 background: green; 11 } 12 13 </style> 14 15 <script src="鏈式運動框架.js"></script> 16 <script> 17 window.onload=function(){ 18 var oBtn = document.getElementsByTagName('input')[0]; 19 var oDiv = document.getElementById('div1'); 20 oBtn.onclick = function(){ 21 startMove(oDiv,'width',500,function(){ 22 startMove(oDiv,'height',500); 23 }); 24 } 25 } 26 </script> 27 </head> 28 <body> 29 <input type="button" value="運動"> 30 31 <div id="div1"></div> 32 </body> 33 </html>
鏈式運動框架.js代碼:
1 /** 2 * 獲取計算後的樣式 3 * @param obj 對象 4 * @param name 樣式名稱:width/height等 5 * @returns {*} 6 */ 7 function getStyle(obj, name) { 8 if (obj.currentStyle) { 9 return obj.currentStyle[name]; 10 } else { 11 return getComputedStyle(obj, false)[name]; 12 } 13 } 14 15 function startMove(obj, attr, iTarget, fun) { 16 clearInterval(obj.timer); 17 obj.timer = setInterval(function () { 18 var cur; 19 if (attr == 'opacity') { 20 cur = Math.round(parseFloat(getStyle(obj, attr)) * 100); 21 } else { 22 cur = parseInt(getStyle(obj, attr)); 23 } 24 var speed = (iTarget - cur) / 6; 25 speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed); 26 if (cur == iTarget) { 27 clearInterval(obj.timer); 28 if (fun) { 29 fun(); 30 } 31 } else { 32 if (attr == 'opacity') { 33 obj.style.filter = 'alpha(opacity:' + (cur + speed) + ')'; 34 obj.style.opacity = (cur + speed) / 100;//把範圍重新縮小爲0~1之間 35 } else { 36 obj.style[attr] = cur + speed + 'px'; 37 } 38 } 39 }, 30); 40 }
7. 實現完美運動框架
①. 要求:改進鏈式運動框架,鏈式框架沒辦法實現多個“屬性”同時運動!比如width、height同時變化。鏈式運動框架是沒法實現的,所以對此進行改進,也就是最終的運動框架!
②. 具體代碼:
html代碼部分:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title></title> 6 <style> 7 #div1{ 8 width:100px; 9 height:100px; 10 background: black; 11 } 12 </style> 13 <script src="完美運動框架.js"></script> 14 <script> 15 window.onload = function(){ 16 var oBtn = document.getElementById('btn1'); 17 var oDiv = document.getElementById('div1'); 18 oBtn.onclick = function(){ 19 startMove(oDiv,{width:500,height:500},function(){ 20 startMove(oDiv,{width:100,height:100}); 21 }); 22 } 23 } 24 25 </script> 26 </head> 27 <body> 28 <input id="btn1" type="button" value="運動"> 29 <div id="div1"></div> 30 </body> 31 </html>
完美運動框架.js代碼部分:
1 /** 2 * 獲取對象的樣式 3 * @param obj 對象 4 * @param name 樣式名稱 5 */ 6 function getStyle(obj, name) { 7 if (obj.currentStyle) { 8 return obj.currentStyle[name]; 9 } else { 10 return getComputedStyle(obj, false)[name]; 11 } 12 } 13 /** 14 * 完美運動框架實現了鏈式運動框架無法實現多屬性同時運動的情況。如:width/height同時運動 15 * @param obj 16 * @param json 把要運動的屬性通過json方式傳入。如:{width:500,height:500} 17 * @param fun 執行完動作後,需要調用的方法 18 */ 19 function startMove(obj, json, fun) { 20 clearTimeout(obj.timer); 21 obj.timer = setInterval(function () { 22 var stop = true; //用來判斷是否可以關閉定時器 23 for (var item in json) { 24 var cur; 25 if (item == 'opacity') { 26 cur = Math.round(parseFloat(getStyle(obj, item)) * 100); 27 } else { 28 cur = parseInt(getStyle(obj, item)); 29 } 30 var speed = (json[item] - cur) / 6; 31 speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed); 32 if (cur != json[item]) { //判斷當前對象的值是否已經達到目標值 33 stop = false; //未達到目標值時,讓stop爲false。 34 } 35 if (item == 'opacity') { 36 obj.style.filter = 'alpha(opacity:' + (cur + speed) + ')'; 37 obj.style.opacity = (cur + speed) / 100;//把範圍重新縮小爲0~1之間 38 } else { 39 obj.style[item] = cur + speed + 'px'; 40 } 41 if(stop){ 42 clearInterval(obj.timer); 43 if(fun){fun();} 44 } 45 } 46 }, 30); 47 }
聲明:這些知識點都來自智能社的視頻所得~~