Skip to content

Instantly share code, notes, and snippets.

@volkanongun
Created November 28, 2012 10:18
Show Gist options
  • Save volkanongun/4160312 to your computer and use it in GitHub Desktop.
Save volkanongun/4160312 to your computer and use it in GitHub Desktop.
A CodePen by Volkan Ongun. Nebular - Nebula generator. Includes star clustering, background stars, nebula clouds and interstellar dust. Click canvas to re-draw.
<!-- click canvas to draw a new nebula -->
<div id="status">&nbsp;</div>
var canvas, c, w, h,
twoPI = Math.PI * 2,
mX, mY, status;
window.onload = function(){
canvas = document.createElement('canvas')
w = canvas.width = window.innerWidth - 40;
h = canvas.height = window.innerHeight - 40;
c = canvas.getContext('2d');
status = document.getElementById("status");
document.body.appendChild(canvas);
generate();
canvas.addEventListener('click', function(){
generate();
});
window.addEventListener('resize', function(){
canvas.width = w = window.innerWidth - 40;
canvas.height = h = window.innerHeight - 40;
});
}
function generate(){
c.clearRect(0,0,w,h);
status.style.display = "block";
status.innerHTML = "[ generating nebula ]";
window.setTimeout( function(){
var nebula = new Nebula(6,100);
}, 100);
}
function Star (x, y, r, c, b){
this.x = x;
this.y = y;
this.r = r;
this.c = c;
this.b = b;
}
function Colour (h, s, l, a){
this.h = h;
this.s = s;
this.l = l;
this.a = a;
this.fillStyle = function(){
return "hsla(" + this.h + "," + this.s + "%," + l + "%," + this.a + ")";
};
}
function Nebula (clusters,starsPerCluster){
this.points = [];
this.draw = function(){
var p = this.points;
// background star-field
c.fillStyle = "hsla(0,100%,100%,1)";
for(var i = 0; i < 1000; i++){
c.beginPath();
c.arc(Math.random()*w, Math.random()*h, Math.random()*0.75, 0, twoPI, true);
c.closePath();
c.fill();
}
// nebula clouds
c.globalCompositeOperation = "lighter";
for(var i = 0; i < p.length; i ++){
var grad = c.createRadialGradient(p[i].x, p[i].y, p[i].r, p[i].x, p[i].y, p[i].b);
grad.addColorStop(0, "hsla(" + p[i].c.h + ",100%,20%,0.06)");
grad.addColorStop(1, "hsla(" + p[i].c.h + ",100%,20%,0)" );
c.fillStyle = grad;
c.beginPath();
c.arc(p[i].x, p[i].y, p[i].b, 0, twoPI, true);
c.closePath();
c.fill();
}
// nebula stars
for(var i = 0; i < p.length; i++){
c.beginPath();
c.arc(p[i].x, p[i].y, p[i].r, 0, twoPI, true);
c.closePath();
c.fillStyle = p[i].c.fillStyle();
c.fill();
}
// interstellar dust
c.globalCompositeOperation = "source-over";
var x1 = 0,
y1 = Math.random() * h * 0.40 + h * 0.30,
x2 = w,
y2 = Math.random() * h * 0.40 + h * 0.30,
v1 = x2-x1,
v2 = y2-y1,
vD = Math.sqrt(v1*v1 + v2*v2),
vA = Math.atan2(v2, v1);
for(var i = 0; i < 1000; i++){
var rnd = i - 500,
r = Math.abs(Math.random()*rnd/2)+10,
x = x1 + (Math.cos(vA) * vD/1000 * i) + Math.random() * rnd - rnd/2,
y = y1 + (Math.sin(vA) * vD/1000 * i) + Math.random() * rnd - rnd/2,
grad = c.createRadialGradient(x,y,0,x,y,r);
grad.addColorStop(0, "hsla(0,0%,0%,0.08)");
grad.addColorStop(1, "hsla(0,0%,0%,0)");
c.fillStyle = grad;
c.beginPath();
c.arc(x,y,r,0,twoPI,true);
c.closePath();
c.fill();
}
c.fillStyle = "hsla(0,100%,100%,0.25)";
for(var i = 0; i < 200; i++){
c.beginPath();
c.arc(Math.random()*w, Math.random()*h, Math.random()*0.75, 0, twoPI, true);
c.closePath();
c.fill();
}
// close stars
c.globalCompositeOperation = "lighter";
for(var i = 0; i < 5; i++){
var x = Math.random()*w,
y = Math.random()*h,
r = Math.random()*400,
hue = Math.floor(Math.random()*360),
grad = c.createRadialGradient(x,y,0,x,y,r);
grad.addColorStop(0, "hsla(" + hue + "0,25%,100%,1)");
grad.addColorStop(0.01, "hsla(" + hue + ",25%,75%,0.75)");
grad.addColorStop(1, "hsla(" + hue + ",0%,0%,0)");
c.fillStyle = grad;
c.beginPath();
c.arc(x,y,r,0,twoPI,true);
c.closePath();
c.fill();
}
window.setTimeout( function(){
status.style.display = "none";
}, 500);
};
this.init = function(){
for(var j = 0; j < clusters; j++){
var x1 = Math.random() * w * 0.50 + w * 0.25,
y1 = Math.random() * h * 0.40 + h * 0.30;
for(var i = 0; i < starsPerCluster; i++){
var x = x1 + Math.cos(Math.random()*twoPI) * (Math.random() * 7000/(i+1)),
y = y1 + Math.sin(Math.random()*twoPI) * (Math.random() * 7000/(i+1)),
r = Math.random()*2;
if(x > w) continue;
if(x < 0) continue;
if(y > h) continue;
if(y < 0) continue;
var col = new Colour( Math.random()*360, 50, Math.floor(Math.random()*50+50), 1 );
this.points.push( new Star(x, y, r, col, Math.random()*200) );
}
}
this.draw();
};
this.init();
};
*{margin:0;padding:0;-moz-box-sizing:border-box;-webkit-box-sizing:border-box}
body{font-size:75%;background:#222;font-family:arial;padding:20px 0 0 20px}
canvas{border:1px solid #181818;display:block;box-shadow:0 0 10px #111;background:#000}
#status{position:absolute;left:50%;top:50%;margin:-25px 0 0 -150px;width:300px;height:50px;background:#111;border:1px solid #181818;box-shadow:0 0 10px #000;font-size:10px;text-transform:uppercase;color:#888;text-align:center;line-height:50px;display:none;}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment