var canvas = document.getElementById('canvas'); var ctx = canvas.getContext('2d'); 'floor|random|round|abs|sqrt|PI|atan2|sin|cos|pow|max|min' .split('|') .forEach(function(p) { window[p] = Math[p]; }); var TAU = PI*2; function r(n) { return random()*n; } function rrng(lo, hi) { return lo + r(hi-lo); } function rint(lo, hi) { return lo + floor(r(hi - lo + 1)); } function choose(args) { return args[rint(0, args.length-1)]; } /*---------------------------------------------------------------------------*/ var W, H, frame, t0, time, DPR; function resize() { var w = innerWidth; var h = innerHeight; DPR = devicePixelRatio || 1; canvas.style.width = w+'px'; canvas.style.height = h+'px'; W = canvas.width = w * DPR; H = canvas.height = h * DPR; } function loop(t) { // console.log(1000/(t-t0)); t0 = t; frame = requestAnimationFrame(loop); draw(); time++; } function pause() { cancelAnimationFrame(frame); frame = frame ? null : requestAnimationFrame(loop); } function reset() { cancelAnimationFrame(frame); resize(); ctx.clearRect(0, 0, W, H); init(); time = 0; frame = requestAnimationFrame(loop); } /*---------------------------------------------------------------------------*/ function Particle(x, y, vx, vy, color) { this.px = x; this.py = y; this.x = x + vx; this.y = y + vy; this.vx = vx; this.vy = vy; this.color = color; } Particle.prototype.integrate = function() { this.vx = this.x - this.px; this.vy = this.y - this.py; this.px = this.x; this.py = this.y this.vy *= DAMP; this.vx *= DAMP; }; Particle.prototype.move = function() { this.x += this.vx; this.y += this.vy; }; Particle.prototype.gravitateTo = function(x, y) { var dx = x - this.x; var dy = y - this.y; var d = sqrt(dx*dx + dy*dy); this.vx += dx/d; this.vy += dy/d; }; Particle.prototype.draw = function() { ctx.moveTo(this.px, this.py); ctx.lineTo(this.x, this.y); }; /*---------------------------------------------------------------------------*/ var DAMP = 1; var particles; var gravitrons, G; function color(n) { n = 64+floor(64*n); return 'rgba('+0+','+n+','+n+', 0.05)'; } function init() { spawnParticles(); DAMP = 0.89; } function spawnParticles() { N = 0; particles = []; for (var x = W/2 - 35; x < W/2 + 35; x += 1) for (var y = H/2 - 35; y < H/2 + 35; y += 1) particles[N++] = new Particle(x, y, 0, 0, color(0.5)); for (var i = 0; i < N; i++) particles[i].friend = choose(particles); } function draw() { ctx.beginPath(); for (var i = 0; i < N; i++) { var p = particles[i]; var f = p.friend; p.draw(); p.integrate(); p.gravitateTo(f.x, f.y); p.move(); } ctx.strokeStyle = color((time < 300 ? time : 600 - time) / 300); ctx.stroke(); if (time == 300) time = 0; DAMP *= 0.99996; } /*---------------------------------------------------------------------------*/ document.onclick = pause; document.ondblclick = reset; reset();