原生js的彈力小球

有段日子沒發博客了,今天來一彈。css

此次發的東西,難度比較大,用原生js,寫的一個彈力小球,並且是羣發,下面是一張截圖。html

每一次點擊「添加小球」,都會觸發程序,新創造一個div盒子、定義css樣式,而後塞進大盒子中。數組

接着,給這個div小球創造一個定時器,讓他開始移動,而且在碰到牆壁時,會中止勻速運行的定時器,執行另外一個函數,開啓變速移動的定時器,同時對div小球開啓進行變形定時器,實現碰到牆壁後的減速、變形、改變方向、再加速和恢復體形。瀏覽器

講述原理比較簡單,而真正作起來,就麻煩了。app

程序中事先聲明瞭不少數組,每一個數組,分別用來保存小球的軸向速度、定時器、碰到牆壁時的定時器、判讀是否碰到了牆壁、碰到牆壁時的寬度和高度的尺寸等等,太多了。數組中的每一項,對應不一樣的小球,很麻煩。dom

試想過,把每一個小球封裝成一個對象,畢竟js是基於對象的語言,可是一琢磨,發現改起來還不是個小工程,也就放棄了這個打算,仍是之後再有好玩兒的案例,事先想好吧。函數

下面是這個程序運行時的動態圖,再下面,就是完整代碼了,和以前的同樣,直接整個複製,保存到txt,而後改後綴名爲html,再雙擊用瀏覽器打開,就能夠玩兒了。spa

 

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        #ballBox {
            position: relative;
            margin: 0 auto;
            overflow: hidden;
            background-color: #000;
        }
        #ballBox div {
            text-align: center;
            font-family: "微軟雅黑";
            font-weight: bold;
            color: #fff;
        }
        #ballBox button {
            outline:none;
            cursor: pointer;
            border:none;
            background-color: #fff;
            height: 50px;
            position: absolute;
            padding: 0 10px;
            top: 20px;
            left: 50%;
            font: 20px "微軟雅黑";
            margin-left: -70px;
            z-index: 5;
        }
        #ballBox button:active {
            background-color: #bbb;
        }
    </style>
</head>
<body>
<div id="ballBox">
    <button>添加小球(0)</button>
</div>
</body>
<script>
    var ballBox = document.getElementById("ballBox");
    var ballBtn = ballBox.getElementsByTagName("button")[0];
    var div = ballBox.getElementsByTagName("div");
    var timerX = []; //x方向 定時器
    var timerY = []; //y方向 定時器
    var timerXX = []; //x方向碰壁反彈時的定時器
    var timerYY = []; //y方向碰壁反彈時的定時器
    var positionX = [];  //設置這個小球的位置的初始的X軸座標
    var positionY = [];  //設置這個小球的位置的初始的y軸座標
    var boolX = [];  //用來判斷小球是否碰到過牆壁,用不用反方向
    var boolY = [];  //用來判斷小球是否碰到過牆壁,用不用反方向
    var i = []; // 小球碰到牆壁,減速加速時使用
    var width = [];   //小球碰到牆壁時,每次運行定時器時小球的寬度
    var height = [];      //小球碰到牆壁時,每次運行定時器時小球的高度
    var initialW = document.documentElement.clientWidth;  //小球彈跳區域的大小,這裏設置的是可視區域
    var initialH = document.documentElement.clientHeight;  //小球彈跳區域的大小,這裏設置的是可視區域
    ballBox.style.width = initialW + "px";
    ballBox.style.height = initialH + "px";
    var num = 0;// 用來記錄新生成小球的個數,同時做爲小球的索引值
    var number = [];  //用來記錄小球撞過幾回牆壁
    var colorArr = ["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"]; //用來生成隨機顏色
    ballBtn.onclick = function() {
        ballBtn.innerHTML = "添加小球("+ (num+1) +")";
        var color = "";//用來隨機生成顏色
        for (var i = 0; i < 6; i++) {
            color += colorArr[Math.floor(Math.random()*16)];
        }
        var temp = [];  //臨時數組,用來放三個隨機數
        do {
            temp[0] = Math.random()*60;
        }while(temp[0] < 35)  //生成一個隨機數,用來作爲小球的直徑;
        do {
            temp[1] = Math.random()*4;
        }while(temp[1] < 1)  //生成一個隨機數,用來作爲小球x方向的步長;
        do {
            temp[2] = Math.random()*4;
        }while(temp[2] < 1)  //生成一個隨機數,用來作爲小球y方向的步長;
        var newDiv = document.createElement("div");
        newDiv.style.position = "absolute";  //設置小球的一系列屬性,大小,顏色等等
        newDiv.style.width = temp[0] + "px";
        newDiv.style.height = temp[0] + "px";
        newDiv.style.borderRadius = "50%";
        newDiv.style.backgroundColor = "#" + color ;
        newDiv.style.top = 0;
        newDiv.style.left = 0;
        newDiv.title = num++;  //設置索引
        newDiv.style.fontSize = temp[0]/2 + "px";
        newDiv.style.lineHeight = temp[0] + "px";
        number[number.length] = 0;
        newDiv.innerHTML = number[number.length - 1];
        positionX[positionX.length] = 0;  //設置這個小球的位置的初始的X軸座標也就是小球出發的位置
        positionY[positionY.length] = 0;  //設置這個小球的位置的初始的y軸座標也就是小球出發的位置
        boolX[boolX.length]= false;  //用來判讀小球是否碰到過牆壁,用不用反方向
        boolY[boolY.length]= false;  //用來判讀小球是否碰到過牆壁,用不用反方向
        ballBox.appendChild(newDiv);
        timerX[timerX.length] = setInterval("moveX("+temp[0]+","+temp[1]+","+ (div.length-1) +")",10);
        timerY[timerY.length] = setInterval("moveY("+temp[0]+","+temp[2]+","+ (div.length-1) +")",10);
    }
    document.onkeydown = function() {   //按下鍵盤事件
        ballBtn.onclick();
        ballBtn.style.backgroundColor = "#bbb";
    }
    document.onkeyup = function() {   //按下鍵盤事件
        ballBtn.style.backgroundColor = "#fff";
    }
    function moveX(dia,x,index) {      //小球x軸方向的位移函數
        if (positionX[index]+x > initialW-dia) {  //if用來判斷小球是否須要換方向
            clearInterval(timerX[index]);
            div[index].style.left = "";
            div[index].style.right =  "0";
            i[index] = 0;
            number[index]++;
            div[index].innerHTML = number[index];
            timerXX[index] = setInterval("fn("+x+","+index+ ","+ dia +",'right')",10);
            return;
        }
        if (positionX[index]+x < 0) {  //if用來判斷小球是否須要換方向
            clearInterval(timerX[index]);
            div[index].style.left = "0";
            i[index] = 0;
            number[index]++;
            div[index].innerHTML = number[index];
            timerXX[index] = setInterval("fn("+x+","+index+ ","+ dia +",'left')",10);
            return;
        }
        positionX[index] += x;
        div[index].style.left =  positionX[index] + "px";  //設定此小球距離左端的距離
    }
    function moveY(dia,y,index) {      //小球y軸方向的位移函數
        if (positionY[index]+y > initialH-dia) {  //if用來判斷小球是否須要換方向
            clearInterval(timerY[index]);
            div[index].style.top = "";
            div[index].style.bottom =  "0";
            i[index] = 0;
            number[index]++;
            div[index].innerHTML = number[index];
            timerYY[index] = setInterval("fn("+y+","+index+ ","+ dia +",'bottom')",10);
            return;
        }
        if (positionY[index]+y < 0) {  //if用來判斷小球是否須要換方向
            clearInterval(timerY[index]);
            div[index].style.top = "0";
            i[index] = 0;
            number[index]++;
            div[index].innerHTML = number[index];
            timerYY[index] = setInterval("fn("+y+","+index+ ","+ dia +",'top')",10);
            return;
        }
        positionY[index] += y;
        div[index].style.top =  positionY[index] + "px";   //設定此小球距離頂端的距離
    }
    function fn(k,index,dia,direction) {
        width[index] = div[index].scrollWidth;
        height[index] = div[index].scrollHeight;
        k = -k;
        //  判斷是否已經反彈完成,該脫離牆壁了
        if ( -(Math.abs(k)+i[index]) > Math.abs(k)) {
            div[index].style.width = dia + "px";        //使寬高均爲原始大小
            div[index].style.height = dia + "px";       //使寬高均爲原始大小
            //判斷是左右方向撞牆仍是上下方向,須要調用不一樣的定時器
            if (direction == "left"||direction == "right") {
                clearInterval(timerXX[index]);
                timerX[index] = setInterval("moveX("+dia+","+k+","+ index +")",10);
                return ;
            }else {
                clearInterval(timerYY[index]);
                timerY[index] = setInterval("moveY("+dia+","+k+","+ index +")",10);
                return ;
            }
        }
        i[index] -= 0.4;
        if (direction == "left") {
            k += i[index];
            var width2 = width[index] - k;
            var height2 = height[index] + k;
        }else if (direction == "right"){
            k -= i[index];
            var width2 = width[index] + k;
            var height2 = height[index] - k;
        }else if (direction == "top") {
            k += i[index];
            var width2 = width[index] + k;
            var height2 = height[index] - k;
        }else{
            k -= i[index];
            var width2 = width[index] - k;
            var height2 = height[index] + k;
        }
        div[index].style.width = width2 + "px";
        div[index].style.height = height2 + "px";
    }
</script>
</html>

<!--加速度的定義是△v/△t,這是通常的求法-->
<!--還有就是利用牛頓第二定律,F=ma,能夠先求合外力,再比上質量就是加速度a-->
<!--還能夠利用運動學公式X=1/2at²+v0t或者v²-v0²=2ax求出-->
相關文章
相關標籤/搜索