HTML。div.ms は中央揃え。
<canvas id="Canvas"></canvas> <br> <div class="ms" style="color: blue;">クリックして下さい</div> <form> <div class="ms"><input type="button" value="消去" onclick="cvsClear();"></div> </form> <br> <div class="ms"><a href="canvas_sample3_code.html">Code</a></div>
JavaScript
var wd, cvs, ctx, r, num; //円クラス var Circle = function () { this.dist = function (c) { //円の中心どうしの距離 return Math.sqrt(this.o.sub(c.o).absl2()) }; }; //ベクトル・クラス var Vector = function (x, y) { this.x = x; this.y = y; this.mul = function (a) { //a倍 return new Vector(a * this.x, a * this.y); }; this.innPro = function (v) { //内積 return this.x * v.x + this.y * v.y; }; this.add = function (v) { //和 return new Vector(this.x + v.x, this.y + v.y); }; this.sub = function (v) { //差 return new Vector(this.x - v.x, this.y - v.y); }; this.absl2 = function () { //絶対値の二乗 return Math.pow(this.x, 2) + Math.pow(this.y, 2); }; }; //開始 var cir = []; //円を表すインスタンス(配列) wd = 500; r = 20; num = 0; //wdはCanvasの縦横, rは円の半径, numは円の個数 onload = function() { cvs = document.getElementById("Canvas"); ctx = cvs.getContext("2d"); cvs.height = wd; cvs.width = wd; cvs.onclick = setBall; //クリックされたら円生成 setInterval(f, 10); } //メインの処理 function f() { if (num == 0) {return;} ctx.clearRect(0, 0, wd, wd); //画面クリア var fl = geneArray(num); //円が既に処理されていれば false、まだ処理していないのは true。 for (var i = 0; i < num; i++) { ctx.beginPath(); ctx.fillStyle = cir[i].cl; ctx.arc(cir[i].o.x, cir[i].o.y, r, 0, Math.PI * 2); ctx.fill(); cir[i].o = cir[i].o.add(cir[i].v); //円の移動計算 if (cir[i].o.x >= wd - r || cir[i].o.x <= r) {cir[i].v.x = -cir[i].v.x;} //壁と衝突するか else if (cir[i].o.y >= wd - r || cir[i].o.y <= r) { cir[i].v.y = -cir[i].v.y; } for (var j = 0; j < num; j++) { if (!fl[i][j]) {continue;} //処理の終った円はスキップする var c1 = cir[i], c2 = cir[j]; if (c1.dist(c2) <= r * 2) { //円どうしの衝突判定 var v1 = c1.v, v2 = c2.v; var ra = c1.o.sub(c2.o); var tmp = ra.mul(ra.innPro(v1.sub(v2)) / ra.absl2()); c1.v = v1.sub(tmp); c2.v = v2.add(tmp); fl[i][j] = false; } } } } //Array生成 function geneArray(n) { var a = new Array(n); for (var i = 0; i < n; i++) { a[i] = new Array(n); for (var j = 0; j < n; j++) { a[i][j] = true; if (i <= j) {a[i][j] = false;} } } return a; } //円の生成 function setBall(e) { //eはイベント(マウス・クリック) var x1, y1; x1 = e.pageX - cvs.offsetLeft; y1 = e.pageY - cvs.offsetTop; if (x1 <= r || x1 >= wd - r || y1 <= r || y1 >= wd - r) {return;} num++; cir[num - 1] = new Circle(); //インスタンス生成 cir[num - 1].o = new Vector(x1, y1); //中心 cir[num - 1].v = new Vector((Math.random() * 2 + 2) * (Math.random() - 0.5) * 2, (Math.random() * 2 + 2) * (Math.random() - 0.5) * 2); //円の速度ベクトルをランダムに生成 cir[num - 1].cl = "rgb(" + rnd() + "," + rnd() + "," + rnd() + ")"; //円の色 if (near(num - 1)) {num--; pop(cir); return;} //円どうしが近すぎれば生成しない } //円どうしが近いか function near(i) { if (i == 0) {return false;} for (var j = 0; j < i; j++) { if (cir[i].dist(cir[j]) <= r * 2) {return true;} } return false; } function rnd() { return String(Math.floor(Math.random()*256)); } //リセット function cvsClear() { ctx.clearRect(0, 0, wd, wd); num = 0; }