1. 程式人生 > 實用技巧 >【JavaScript】物件構建實踐

【JavaScript】物件構建實踐

以下內容為學習記錄,可以參考 MDN 原文。

環境

  • vscode 1.46
  • Microsoft Edge 83

概述

本文通過編寫一個彈球 demo 來展示 JavaScript 中物件的重要性。
我們的小球會在螢幕上彈跳,當它們碰到彼此時會變色。

定義 html

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>彈跳綵球</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <h1>彈跳綵球</h1>
  <canvas></canvas>

  <script src="main.js"></script>
</body>

</html>

定義樣式表

html, body {
  margin: 0;
}

html {
  font-family: sans-serif;
  height: 100%;
}

body {
  overflow: hidden;
  height: inherit;
}

h1 {
  font-size: 2rem;
  letter-spacing: -1px;
  position: absolute;
  margin: 0;
  top: -4px;
  right: 5px;

  color: transparent;
  text-shadow: 0 0 4px white;
}

定義畫布

// 設定畫布

const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");

const width = canvas.width = window.innerWidth;
const height = canvas.height = window.innerHeight;

隨機值函式

/**
 * 生成隨機數的函式
 * @param {number} min 最小值
 * @param {number} max 最大值
 * @return {number} 隨機值
 */
function random(min, max) {
  const num = Math.floor(Math.random() * (max - min)) + min;
  return num;
}

定義小球模型

function Ball(x, y, velX, velY, color, size) {
  this.x = x;
  this.y = y;
  this.velX = velX;
  this.velY = velY;
  this.color = color;
  this.size = size;
}

畫小球

Ball.prototype.draw = function() {
  ctx.beginPath();
  ctx.fillStyle = this.color;
  ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
  ctx.fill();
}

更新小球位置

Ball.prototype.update = function() {
  if ((this.x + this.size) >= width) {
    this.velX = -(this.velX);
  }

  if ((this.x - this.size) <= 0) {
    this.velX = -(this.velX);
  }

  if ((this.y + this.size) >= height) {
    this.velY = -(this.velY);
  }

  if ((this.y - this.size) <= 0) {
    this.velY = -(this.velY);
  }

  this.x += this.velX;
  this.y += this.velY;
}

生成多個小球

let balls = [];

while (balls.length < 25) {
    let size = random(10, 20);
    let ball = new Ball(
      // 為避免繪製錯誤,球至少離畫布邊緣球本身一倍寬度的距離
      random(0 + size, width - size),
      random(0 + size, height - size),
      random(-7, 7),
      random(-7, 7),
      randomColor(),
      size
    );
    balls.push(ball);
  }

填充畫布

function loop() {
  ctx.fillStyle = 'rgba(0, 0, 0, 0.25)';
  ctx.fillRect(0, 0, width, height);

  for (let i = 0; i < balls.length; i++) {
    balls[i].draw();
    balls[i].update();
  }

  requestAnimationFrame(loop);
}

最後

loop();

Ball.prototype.collisionDetect = function() {
  for (let j = 0; j < balls.length; j++) {
    if (this !== balls[j]) {
      const dx = this.x - balls[j].x;
      const dy = this.y - balls[j].y;
      const distance = Math.sqrt(dx * dx + dy * dy);

      if (distance < this.size + balls[j].size) {
        balls[j].color = this.color = randomColor();
      }
    }
  }
}

balls[i].collisionDetect();