前 言
MYBG
小編最近在做自己的個人網站,其中就用到了一個小球碰撞檢測的功能,想自己寫,無奈本人能力不足啊(畢竟還是一個菜鳥)!!就想着找個插件用一下也好,可是找了好久也沒有找到一個比較好用的。好在天無絕人之路,在不斷的搜搜巡巡過程中,還是發現了一個,用原生js實現小球碰撞檢測的方法,下面分享給大家。
注:本文參考“敲代碼不愛找bug的妹子”的一篇博客,詳解可參考:http://blog.csdn.net/new_codeer/article/details/52386566
參考過后,經過對原文進行了稍微的改動,特別適用於網站的開發。復制過去,稍微改動一下即可。具體的原代碼如下:
| 一、HTML代碼(body部分) |
1 <body> 2 <!--只需要做一個大div包裹幾個小div即可,你想要幾個小球碰撞就在內部做幾個div即可,這里我們做了6個小球--> 3 <div id="main"> 4 <div></div> 5 <div></div> 6 <div></div> 7 <div></div> 8 <div></div> 9 <div></div> 10 </div> 11 </body>
上面body部分這樣就算是完成了,下面我們給body中的div做一些小樣式。
| 二、CSS小球樣式部分 |
1 <style type="text/css"> 2 /*將body默認的margin和padding部分去掉*/ 3 *{ 4 margin: 0px; 5 padding: 0px; 6 } 7 /*采用定位的方式,讓小球運動起來*/ 8 #main{ 9 margin: 0px auto; 10 position: relative; 11 } 12 /*小球的樣式*/ 13 #main div{ 14 overflow: hidden; 15 position: absolute; 16 width: 80px; 17 height: 80px; 18 opacity: 0.5; 19 border-radius: 50%; 20 background-color: red; 21 } 22 </style>
小球是要運動起來的,我們通過給小球和它的父元素添加定位,最后用js改變其top、bottom、left、right值來讓小球運動。現在我們小球的樣式已經做好了,下面的js代碼才是重中之重。
| 3.1 Android 事件基礎知識 |
1 <script type="text/javascript"> 2 var main = document.getElementById("main"); //取到小球父元素 3 var circles = main.getElementsByTagName("div"); //取到小球 4 var st = [0,1,2,3,4,5,6,7,8,9]; 5 var json = [],arr = [],color = []; 6 var maxW = 0; 7 var maxH = 0; 8 var cwidth = circles[0].offsetWidth; //對象可見寬度 9 var cheight = circles[0].offsetHeight; //對象可見高度 10 11 //根據瀏覽器窗口的大小自動調節小球的運動空間 12 window.onresize=function(){ 13 maxW=window.innerWidth-circles[0].clientWidth;//小球運動的最大寬度 14 maxH=window.innerHeight-circles[0].clientHeight;//小球運動的最大高度 15 main.style.width = window.innerWidth+"px"; 16 main.style.height = window.innerHeight+"px"; 17 } 18 onresize(); 19 //數組對象的初始化 20 for(var i=0;i<circles.length;i++){ 21 arr=[]; 22 for(var j=0;j<6;j++){ 23 color[j] = st[Math.floor(Math.random()*16)]; 24 } 25 arr.x = Math.floor(Math.random()*(maxW+1));//初始x坐標 26 arr.y = Math.floor(Math.random()*(maxH+1));//初始y坐標 27 arr.cx = arr.x + circles[0].offsetWidth/2; //圓心x坐標 28 arr.cy = arr.y + circles[0].offsetHeight/2; //圓心y坐標 29 arr.movex = Math.floor(Math.random()*2);//x軸移動方向 30 arr.movey = Math.floor(Math.random()*2);//y軸移動方向 31 arr.speed = 2+Math.floor(Math.random()*5);//隨機生成2-6之間的移動速度,如果在做項目的時候,這種隨即生成的速度不想用的話,可以直接給speed賦值,
固定小球的速度即可。如以下代碼: 32 //arr.speed = 1.5; 34 arr.timer = null;//計時器 35 arr.index = i;//索引值 36 json.push(arr); 37 circles[i].style.left = arr.x + "px";//小球位置初始化 38 circles[i].style.top = arr.y + "px";//小球位置初始化 39 } 40 //碰撞函數 41 function crash(a){ 42 var ball1x = json[a].cx; 43 var ball1y = json[a].cy; 44 for(var i= 0;i<json.length;i++){ 45 if(i!=a){ 46 var ball2x = json[i].cx; 47 var ball2y = json[i].cy; 48 //圓心距離的平方 49 var len = (ball1x-ball2x)*(ball1x-ball2x)+(ball1y-ball2y)*(ball1y-ball2y); 50 if(len <= cwidth*cwidth){ 51 //小球位置的判斷,發生碰撞反應 52 if(ball1x >ball2x){ 53 if(ball1y > ball2y){ 54 json[a].movex=1; 55 json[a].movey=1; 56 }else if(ball1y < ball2y){ 57 json[a].movex=1; 58 json[a].movey=0; 59 }else{ 60 json[a].movex=1; 61 } 62 }else if(ball1x < ball2x){ 63 if(ball1y > ball2y){ 64 json[a].movex=0; 65 json[a].movey=0; 66 }else if(ball1y < ball2y){ 67 json[a].movex=0; 68 json[a].movey=1; 69 }else{ 70 json[a].movex=0; 71 } 72 }else{ 73 if(ball1y > ball2y){ 74 json[a].movey=1; 75 }else if(ball1y < ball2y){ 76 json[a].movey=0; 77 } 78 } 79 } 80 } 81 82 } 83 } 84 //移動函數 85 function move(circle){ 86 circle.timer = setInterval(function () { 87 if(circle.movex == 1){ 88 circle.x+=circle.speed; 89 if(circle.x+circle.speed >= maxW){//防止小球出界 90 circle.x = maxW; 91 circle.movex=0;//小球運動方向發生改變 92 } 93 }else{ 94 circle.x-=circle.speed; 95 if(circle.x-circle.speed <= 0){ 96 circle.x = 0; 97 circle.movex=1; 98 } 99 } 100 if(circle.movey == 1){ 101 circle.y += circle.speed; 102 if(circle.y+circle.speed >= maxH){ 103 circle.y = maxH; 104 circle.movey=0; 105 } 106 }else{ 107 circle.y-=circle.speed; 108 if(circle.y-circle.speed <= 0){ 109 circle.y = 0; 110 circle.movey=1; 111 } 112 } 113 circle.cx = circle.x + circles[0].offsetWidth/2;//小球每一次運動圓心都會發生改變 114 circle.cy = circle.y + circles[0].offsetHeight/2; 115 circles[circle.index].style.left = circle.x + "px";//小球位置重定位 116 circles[circle.index].style.top = circle.y + "px"; 117 crash(circle.index); 118 },15); 119 } 120 //對每一個小球綁定計時器,讓小球動起來 121 for(var i=0;i<circles.length;i++){ 122 move(json[i]); 123 } 124 </script>
其實,我們通過上面的代碼就可以完全實現一個小球碰撞檢測的功能了。但是僅僅是上面的代碼,還是會存在一定的bug,就是當整個網站存在右側滾動條時,當小球碰到屏幕右側的時候,會出現一瞬的橫向滾動條,這就是做網站比較忌諱的了,橫向滾動條的出現太丑了。所以我們可以通過以下代碼來解決。
1 //滾動條寬度計算函數 2 function getScrollbarWidth() { 3 var oP = document.createElement("p"), 4 styles = { 5 width: "100px", 6 height: "100px", 7 overflowY: "scroll" 8 }, i, scrollbarWidth; 9 for (i in styles) oP.style[i] = styles[i]; 10 document.body.appendChild(oP); 11 scrollbarWidth = oP.offsetWidth - oP.clientWidth; 12 oP.remove(); 13 return scrollbarWidth; 14 }
以上是一個計算滾動條寬度的函數,此函數可以計算右側滾動條的寬度,我們只需要在“根據瀏覽器窗口的大小自動調節小球的運動空間”上面,調用此函數
var scrollbarWidth = getScrollbarWidth(); 再修改小球的最大運動寬度 maxW=window.innerWidth-circles[0].clientWidth-scrollbarWidth ;這樣這個bug就修改好了。
編者按
這個是我在做項目時的親身經歷,覺得這個寫得特別好用,就拿過來與大家分享一下。希望對大家有那么一點點兒幫助吧!!最后還要感謝一下“敲代碼不愛找bug的妹子”幫我解決了一個大問題。。
