interactive Art

addEventListener(‘click’, function(e){})で、push(new Ball(x, y, r))します。ランダム関数の範囲をとる際には、return min + Math.floor(Math.random() * (max – min + 1))と書きます。また、ボールの移動は、x++, y++, バウンドは、x軸、y軸をそれぞれ-1をかけてあげます。

reference
.getBoundingClientRect():returns the size of an element and its position relative to the viewport.
setTimeout bind: http://stackoverflow.com/questions/2130241/pass-correct-this-context-to-settimeout-callback
Object.prototype: property represents the Object prototype object.

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Intractive Art</title>
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<style>
	</style>
</head>
<body>
	<canvas id="mycanvas" width="500" height="250">
	</canvas>
	<script>
	(function(){
		'use strict';

		var canvas;
		var ctx;
		var Ball;
		var balls = [];
		var Stage;
		var stage;

		canvas = document.getElementById('mycanvas');
		if (!canvas || !canvas.getContext) return false;
		ctx = canvas.getContext('2d');

		function rand(min, max){
			return min + Math.floor(Math.random() * (max - min + 1));
		}

		function adjustPosition(pos, r, max) {
			/*if (x - r < 0) x = r;
			if (y - r < 0) y = r;
			if (x + r > canvas.width) x = canvas.width - r;
			if (y + r > canvas.height) y = canvas.height - r;*/
			if (pos - r < 0){
				return r;
			} else if (pos + r > max){
				return max - r;
			} else {
				return pos;
			}

		}

		canvas.addEventListener('click', function(e){
			var x, y, r;
			var rect;
			/*x = rand(100, 400);
			y = rand(100, 200);*/
			rect = e.target.getBoundingClientRect();
			x = e.clientX - rect.left;
			y = e.clientY - rect.top;

			r = rand(0, 100) < 20 ? rand(50, 80) : rand(10, 35);

			/*if (x - r < 0) x = r;
			if (y - r < 0) y = r;
			if (x + r > canvas.width) x = canvas.width - r;
			if (y + r > canvas.height) y = canvas.height - r;*/
			x = adjustPosition(x, r, canvas.width);
			y = adjustPosition(y, r, canvas.height);
			balls.push(new Ball(x, y, r));
		});

		Ball = function(x, y, r){
			this.x = x;
			this.y = y;
			this.r = r;
			this.vx = rand(-10, 10);
			this.vy = rand(-10, 10);
			this.color = 'hsla(' + rand(50, 100)+ ', ' + rand(40, 80) + '%, ' + rand(50, 60) +'%, ' + Math.random() + ')';
		};

		/*var ball = new Ball(rand(100, 200), rand(100, 200), rand(10, 50));
		ball.draw();*/

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

		};

		Ball.prototype.move = function(){
			if (this.x + this.r > canvas.width || this.x - this.r < 0){
				this.vx *= -1;
			}
			if (this.y + this.r > canvas.height || this.y - this.r < 0){
				this.vy *= -1;
			}
			this.x += this.vx;
			this.y += this.vy;

		};

		Stage = function(){
			this.update = function(){
					var i;
					this.clear();
			
			for (i = 0; i < balls.length; i++){
				balls&#91;i&#93;.draw();
				balls&#91;i&#93;.move();
			}
			setTimeout(function(){
				this.update();
			}.bind(this), 30);

			};
			this.clear = function(){
				ctx.fillStyle = "#ecf0f1";
				ctx.fillRect(0, 0, canvas.width, canvas.height);
			}
		};

		stage = new Stage();
		stage.update();

	})();
	</script>
</body>
</html>