art with code

2009-11-11

Canvas-generated hexa background


Wrote that for the new fancy Metatunnel page (while procrastinating on writing an essay...) Here's the JS to boggle over:

function polygon(n) {
var a = [];
for (var i=0; i<n; i++)
a.push({x:Math.cos(2*Math.PI*(i/n)), y:Math.sin(2*Math.PI*(i/n))});
return a;
}
function id(i){ return i }
function lineTo(ctx){return function (p){ ctx.lineTo(p.x, p.y) }}
function linePath(ctx, path){ path.map(lineTo(ctx)) }
function drawPath(ctx, path, close){
ctx.beginPath(); linePath(ctx, path); if (close) ctx.closePath() }
function strokePath(ctx, path, close){ drawPath(ctx, path, true); ctx.stroke() }
function fillPath(ctx, path){ drawPath(ctx, path); ctx.fill() }
function scale(x,y,p){return {x:p.x*x, y:p.y*y}}
function scalePoint(x,y){return function(p){ return scale(x,y,p) }}
function translate(x,y,p){return {x:p.x+x, y:p.y+y}}
function translatePoint(x,y){return function(p){ return translate(x,y,p) }}
function scalePath(x,y,path){ return path.map(scalePoint(x,y)) }
function translatePath(x,y,path){ return path.map(translatePoint(x,y)) }
function clonePath(path){ return path.map(id) }

function wavePoint(p) {
var np = {
x: (p.x + 1.5*Math.cos((p.x+p.y) / 15)),
y: (p.y + 1.5*Math.sin((p.x+p.y) / 15))
}
var d = Math.sqrt(np.x*np.x + np.y*np.y);
var s = Math.pow(1/(d+1),0.7);
return translate(5, 24, scale(s*30, s*30, np));
}
function wavePath(path){ return path.map(wavePoint) }
function drawbg() {
var canvas = document.createElement('canvas');
canvas.width = 1400;
canvas.height = 700;
var ctx = canvas.getContext('2d');
ctx.fillStyle = '#333';
ctx.fillRect(0,0,canvas.width,canvas.height);
var g = ctx.createRadialGradient(50,50,0, 50,50,1400);
g.addColorStop(0,'rgba(0,192,255,1)');
g.addColorStop(1.0,'rgba(255,0,255,1)');
ctx.fillStyle = g;
var hex = polygon(6);
var s = Math.sin(Math.PI/3);
var c = Math.cos(Math.PI/3);
for (var i=-2; i<120; i++) {
for (var j=0; j<8; j++) {
if (Math.random()+Math.random() < Math.pow((Math.sqrt(i*i+j*j) / 55),2)) continue;
var x = i*(1.2+c);
var y = j*(2.4*s) + (i%2 ? 1.2*s : 0);
fillPath(ctx, scalePath(10, 7, wavePath(translatePath(x,y,hex))));
}
}
document.body.style.background = '#333 url('+canvas.toDataURL()+') no-repeat top left';
}

5 comments:

Alessandro said...

Hi Kig

In your git, I note you are using Canvas3D plugin with context ID as 'moz-glweb20'.
This doesn't work in my browser, so I try to found a solution, using some snipet from cdl3d and nihilog :

[code]
/**
* Get correct Context
*/
function getCanvas3DContext(canvas){
var glCanvas3D;
try{
// Does the user have the Canvas3D plugin?
glCanvas3D = canvas.getContext('moz-glweb20');
}
catch (err){
glCanvas3D = null;
}

if(!glCanvas3D){
try {
// Does the user have a browser that supports WebGL?
// If so, use that instead.
glCanvas3D = canvas.getContext('moz-webgl');

}
catch (err)
{
glCanvas3D = canvas.getContext("webkit-3d");
glCanvas3D = null;
}
}
return glCanvas3D;
}

[/code]

I hope it helps

Ilmari Heikkinen said...

Thanks for finding that!

What file is that and is it still there? I couldn't find any references to moz-glweb20 in the tests at least, maybe I missed something.

Alessandro said...

Hi

At unit.js you have the constant :

GL_CONTEXT_ID = 'moz-glweb20';

This is OK only for Canvas3D plugin, I guess.


Btw, above snipplet has a small error.

This one works better:

function getCanvas3DContext(canvas){
var glCanvas3D;
try{
// Does the user have the Canvas3D plugin?
glCanvas3D = canvas.getContext('moz-glweb20');
} catch (err){
glCanvas3D = null;
}

if(!glCanvas3D){
try {
// Does the user have a browser that supports WebGL?
// If so, use that instead.
//try mozilla
glCanvas3D = canvas.getContext('moz-webgl');
if(!glCanvas3D){
// try webkit
glCanvas3D = canvas.getContext("webkit-3d");
}
}catch (err){
// try webkit once more
glCanvas3D = canvas.getContext("webkit-3d");
}
}
return glCanvas3D;
}

Ilmari Heikkinen said...

That's from an old version, I think. If you have the git repo, update it with git pull.

The current version has GL_CONTEXT_ID detection in util.js:

initGL_CONTEXT_ID = function(){
var c = document.createElement('canvas');
var contextNames = ['webkit-3d','moz-webgl','webgl'];
GL_CONTEXT_ID = null;
for (var i=0; i<contextNames.length; i++) {
try {
if (c.getContext(contextNames[i])) {
GL_CONTEXT_ID = contextNames[i];
break;
}
} catch (e) {}
}
if (!GL_CONTEXT_ID) {
log("No WebGL context found. Unable to run tests.");
}
}
initGL_CONTEXT_ID();

And metatunnel.html had a golfed version:

find=function(a,f){for(var i=0,j;j=a[i],i++<a.length;)if(f(j))return j};
GL_CONTEXT_ID=null;
getGLContext = function(c){
if (!GL_CONTEXT_ID)
GL_CONTEXT_ID = find(['webkit-3d','moz-webgl','webgl'],function(n){try{return c.getContext(n)}catch(e){}});
if (!GL_CONTEXT_ID)
alert("No WebGL context found.");
else return c.getContext(GL_CONTEXT_ID);
}

But now it's a bit longer and friendlier.

Unknown said...

Pretty awesome

Blog Archive