運動的小球

canvas繪制運動小球

知乎的網頁版登錄界面的背景有很多運動的小球,小球和小球運動的時候之間還有連線,給人一種三維立體變換的效果,看著十分的不錯,所以用canvas試著做了個和知乎登錄界面背景類似的效果,上面動圖就是做好效果的截圖。

實現思路

首先了解下canvas中的動畫原理?canvas中的動畫其實是通過不斷的重繪來實現動起來的效果的,打個比方一個小球初始的時候在畫布的X,Y坐標記作ball(x,y),然后每隔10毫秒更改小球的X,Y坐標為ball(x+5,y+5)(在當前X,Y坐標加5個像素) 并且清除整個畫布,重新在畫布上繪制更改坐標后小球,由于10毫秒非常的短,所有在視覺上給我們的感覺就是小球在不斷運動著。canvas繪圖的原理基本就是這樣子。

  1. 定義小球對象
var ball = {
      xPointer: 100, //小球初始x坐標
      yPointer: 100, //小球初始y坐標
      vx: 1, //x方向的速度
      vy: 0.1, //y方向的速度
      x: 1, //x軸運動方向(1表示正方向,-1表示反方向)
      y: -1, //y軸運動方向
      color: "blue", //小球顏色
      radius: 10, //小球半徑
};
  1. 生成小球
    demo中的小球有很多個,所以定義一個數組來裝這些小球,小球的起始坐標、顏色、運動方向都不同所以這些值需要隨機獲取。
   var ballList = []; //小球數組
   var canvas, ctx;
   //生成多個小球
   function initBall() {
       canvas = document.getElementById("canvas");
       ctx = canvas.getContext("2d");
       //循環生成60個小球
       for (var i = 0; i < 60; i++) {
           // console.log(getIndex() + "   " + getIndex())
           var ball = {};
           ball.xPointer = getRandom(20, 980); //隨機小球的X坐標
           ball.yPointer = getRandom(20, 340); //隨機小球的y坐標
           ball.x = getIndex(); //隨機小球x軸運動方向
           ball.y = getIndex(); //隨機小球的y軸運動方向
           ball.vx = Math.random(); //隨機小球x軸方向速度
           ball.vy = Math.random(); //隨機小球y軸方向速度
           ball.radius = 9; //小球半徑
           ball.color = "#" + ("00000" + ((Math.random() * 16777215 + 0.5) >> 0).toString(16)).slice(-6); //隨機小球顏色
           ballList.push(ball);
       }
   }

   //隨機一個1或者-1的方法   
   function getIndex() {
       var arr = [0, 1];
       var index = Math.floor((Math.random() * arr.length));
       if (index == 0) {
           index = -1;
       }
       return index;
   }

   //獲取兩數之間的一個隨機數的方法
   function getRandom(first, last) {
       var choice = last - first + 1;
       return Math.floor(Math.random() * choice + first);
   }
  1. 通過canvas繪制小球
    頁面canvas標簽
<canvas id="canvas" width="1000" height="360" style='background-color: #EEEEEE;'></canvas>

canvas繪制小球代碼

function draw(ctx) {
    ctx.clearRect(0, 0, 1000, 360); //繪制前先清除畫布
    for (var i = 0; i < ballList.length; i++) {
        ctx.save();
        ctx.beginPath();
        ctx.fillStyle = ballList[i].color;
        ctx.arc(ballList[i].xPointer, ballList[i].yPointer, ballList[i].radius, 0, Math.PI * 2, false);
        ctx.closePath();
        ctx.fill();
        ctx.restore();
    }
}
  1. 運動起來
    小球運動的過程中使用了簡單的碰撞檢測,每次到達畫布的邊緣就改變小球的運動方向
//修改小球的狀態,使小球動起來的方法
function update(ballList, ctx) {
    for (var i = 0; i < ballList.length; i++) {
        ballList[i].xPointer += ballList[i].vx * ballList[i].x;
        ballList[i].yPointer += ballList[i].vy * ballList[i].y;
        //碰撞檢測 X軸方向
        if (ballList[i].xPointer + ballList[i].radius >= canvas.width || ballList[i].xPointer - ballList[i].radius <= 0) {
            ballList[i].x = ballList[i].x * -1;
        }
        //碰撞檢測 Y軸方向
        if (ballList[i].yPointer + ballList[i].radius >= canvas.height || ballList[i].yPointer - ballList[i].radius <= 0) {
            ballList[i].y = ballList[i].y * -1;
        }
    }
}
  1. 繪制小球和小球之間的連線
//小球之間連線
function drawLine(ballList, ctx) {
    for (var i = 0; i < ballList.length; i++) {
        for (var j = 0; j < ballList.length; j++) {
            var xx = Math.pow((ballList[i].xPointer - ballList[j].xPointer), 2);
            var yy = Math.pow((ballList[i].yPointer - ballList[j].yPointer), 2);
            var zz = Math.sqrt(xx + yy);
            //判斷兩個小球如果之間距離在20到100之間,就繪制一條直線
            if (zz <= 100 && zz >= 20) {
                console.log(zz)
                ctx.save();
                ctx.beginPath();
                ctx.strokeStyle = "#999999";
                ctx.lineWidth = 0.1;
                // ctx.strokeStyle= "#" + ("00000" + ((Math.random() * 16777215 + 0.5) >> 0).toString(16)).slice(-6);
                ctx.moveTo(ballList[i].xPointer, ballList[i].yPointer);
                ctx.lineTo(ballList[j].xPointer, ballList[j].yPointer);
                ctx.closePath();
                ctx.stroke();
                ctx.restore();
            }
        }
    }
}
  1. 運行
(function() {
    initBall(); //生成小球
    //計時器
    setInterval(function() {
        // console.log(selectfrom(0, 600) + "         " + selectfrom(0, 600));
        draw(ctx); //繪制
        update(ballList, ctx); //修改小球狀態
        drawLine(ballList, ctx); //畫線
    }, 24)
})();

其它

修改小球半徑后的小球運動效果

** 到此一個canvas小球運動效果的demo做完了,看著是不是有一種3d變換效果。**

文章如有誤,請不吝賜教~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容