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[i].draw(); balls[i].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>