如何让多个球在点击时掉落?

How to make multiple balls drop on click?

我有一个球从光标位置掉落,并在光标移动到另一个位置时重新掉落。每次单击鼠标时,我都试图让一个新球掉落。我试过了:

canvas.addEventListener('click', function(event) {
  ball.draw();
});

但是好像没什么作用。有没有什么方法可以在点击时绘制一个新球,而不是一遍又一遍地重新绘制同一个球?

这是代码的其余部分:

var canvas = document.getElementById("canvas"),
    ctx = canvas.getContext("2d");
var W = window.innerWidth,
    H = window.innerHeight;
var running = false;

canvas.height = H; canvas.width = W;

var ball = {},
    gravity = .5,
    bounceFactor = .7;

ball = {
  x: W,
  y: H,
  radius: 15,
  color: "BLUE",
  vx: 0,
  vy: 1,

  draw: function() {
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2, false);
    ctx.fillStyle = this.color;
    ctx.fill();
    ctx.closePath();
  }
};

function clearCanvas() {
  ctx.clearRect(0, 0, W, H);
}

function update() {
  clearCanvas();
  ball.draw();

  ball.y += ball.vy;

  ball.vy += gravity;
  if(ball.y + ball.radius > H) {
    ball.y = H - ball.radius;
    ball.vy *= -bounceFactor;
  }
}

canvas.addEventListener("mousemove", function(e){
  ball.x = e.clientX;
  ball.y = e.clientY;
  ball.draw();
});
setInterval(update, 1000/60);

ball.draw();

只需重写球对象,使其可实例化:

function Ball(W, H) {
  this.x = W;
  this.y = H;
  this.radius = 15;
  this.color = "blue";
  this.vx = 0;
  this.vy = 1;

}

将方法移至原型(这将使它们可以跨实例共享)。此外,添加一个更新方法,以便您可以本地化更新:

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

  update: function() {
    this.y += this.vy;
    this.vy += gravity;
    if(this.y + this.radius > H) {
      this.y = H - this.radius;
      this.vy *= -bounceFactor;
    }
  }
};

在点击事件中(考虑将数组重命名为复数形式 - 这样更容易区分。在您的代码中,您用单个球覆盖 "array"(定义为对象)稍后对象):

var balls = [];                // define an array to hold the balls

为了让点击事件使用鼠标的 x 和 y 位置作为球的起点,我们首先需要调整它,因为它是相对于客户端 window 而不是 canvas.为此,我们获取 canvas 的绝对位置并将其从客户端坐标中减去:

canvas.addEventListener('click', function(event) {
  var rect = this.getBoundingClientRect(),  // adjust mouse position
      x = event.clientX - rect.left,
      y = event.clientY - rect.top;

  balls.push(new Ball(x, y));               // add a new instance
});

现在在主动画循环中迭代数组。每次有一个新球都会被考虑和更新 - 我们只是让循环 运行 直到满足某些条件(未显示):

function update() {
  clearCanvas();

  for(var i = 0, ball; ball = balls[i]; i++) {
    ball.draw();    // this will draw current ball
    ball.update();  // this will update its position
  }

  requestAnimationFrame();
}

实例

如果你把这些放在一起你会得到:

var canvas = document.getElementById("canvas"),
    ctx = canvas.getContext("2d"),
    W = canvas.width, // simplified for demo
    H = canvas.height,
    gravity = .5,
    bounceFactor = .7;

function Ball(x, y) {
  this.x = x;
  this.y = y;
  this.radius = 15;
  this.color = "blue";
  this.vx = 0;
  this.vy = 1
}

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

  update: function() {
    this.y += this.vy;
    this.vy += gravity;  // todo: limit bounce at some point or this value will be added
    if (this.y + this.radius > H) {
      this.y = H - this.radius;
      this.vy *= -bounceFactor;
    }
  }
};

function clearCanvas() {
  ctx.clearRect(0, 0, W, H);
}

var balls = []; // define an array to hold the balls

canvas.addEventListener('click', function(event) {
  var rect = this.getBoundingClientRect(),  // adjust mouse position
      x = event.clientX - rect.left,
      y = event.clientY - rect.top;
  balls.push(new Ball(x, y));               // add a new instance
});


(function update() {
  clearCanvas();

  for (var i = 0, ball; ball = balls[i]; i++) {
    ball.draw(); // this will draw current ball
    ball.update(); // this will update its position
  }

  requestAnimationFrame(update);
})();
canvas {background:#aaa}
<canvas id="canvas" width=600 height=400></canvas>