Object.getOwnPropertyNames(Math).map(function(p) { window[p] = Math[p]; }); if(!hypot) { var hypot = function(x, y) { return sqrt(pow(x, 2) + pow(y, 2)); }; } var rand = function(max, min, is_int) { var max = ((max - 1) || 0) + 1, min = min || 0, gen = min + (max - min)*random(); return (is_int)?round(gen):gen; }; var N_STARS = 8, stars = [], c = document.querySelector('canvas'), ctx = c.getContext('2d'), comet, attraction_pt = null, t = 0, r_id = null; var Star = function(o, φ, r) { var n = (4 + 4)*2; this.o = o || { 'x': rand(w/2, -w/2, 1), 'y': rand(h/2, -h/2, 1) }; this.φ = φ || rand(2*PI); this.r = r || rand(64, 16, 1); this.sv = []; this.init = function() { var α, β = 2*PI/n, x, y, cr; for(var i = 0; i < n; i++) { α = i*β; cr = (i%2 != 0) ? (this.r/16) : (((i%4 == 0)?1:.75)*this.r); x = cr*cos(α); y = cr*sin(α); this.sv.push({ 'x': x, 'y': y }); } }; this.attractedBy = function(p, v) { var p = p || { 'x': 0, 'y': 0 }, v = v || rand(1/30), dx, dy; dx = p.x - this.o.x; dy = p.y - this.o.y; if(hypot(dx, dy) > 1) { this.φ = atan2(dy, dx); this.o.x += v*cos(this.φ); this.o.y += v*sin(this.φ); } else { this.o = { 'x': rand(w/2, -w/2, 1), 'y': rand(h/2, -h/2, 1) }; } }; this.draw = function(cx) { var g = cx.createRadialGradient( 0, 0, 0, 0, 0, this.r/2), a ff = 1 + sin(this.φ + t*PI/rand(60, 20)); cx.save(); cx.translate(this.o.x, this.o.y); cx.rotate(this.φ + t*PI/1800); g.addColorStop(0, 'hsla(70,100%,85%,1)'); g.addColorStop(.25, 'hsla(70,100%,85%,' + ff/8 + ')'); g.addColorStop(1, 'hsla(70,100%,85%,0)'); cx.fillStyle = g; cx.beginPath(); cx.arc(0, 0, this.r/2, 0, 2*PI); cx.closePath(); cx.fill(); g = cx.createRadialGradient( 0, 0, 0, 0, 0, this.r) g.addColorStop(0, 'hsla(20,100%,87%,' + ff/2 + ')'); g.addColorStop(1, 'hsla(20,100%,87%,' + ff/16 + ')'); cx.fillStyle = g; cx.beginPath(); for(var i = 0; i < n; i++) { cx[(i === 0)?'moveTo':'lineTo'](this.sv[i].x, this.sv[i].y); } cx.closePath(); cx.fill(); cx.restore(); }; this.init(); }; var init = function() { var s = getComputedStyle(c); w = c.width = ~~s.width.split('px')[0]; h = c.height = ~~s.height.split('px')[0]; if(r_id) { cancelAnimationFrame(r_id); r_id = null; } stars = []; for(var i = 0; i < N_STARS; i++) { stars.push(new Star()); } ctx.translate(w/2, h/2); draw(); }; var draw = function() { ctx.clearRect(-w/2, -h/2, w, h); for(var i = 0; i < N_STARS; i++) { stars[i].attractedBy(attraction_pt); stars[i].draw(ctx); } t++; r_id = requestAnimationFrame(draw); }; setTimeout(function() { init(); addEventListener('resize', init, false); c.addEventListener('mousemove', function(e) { attraction_pt = { 'x': e.clientX - w/2, 'y': e.clientY - h/2 }; draw(); }, false); }, 15)