Wednesday, June 18th, 2008
Hypno trip down the fractal rug
<>p>
What a great title. It is an entry in the JavaScript 20 liners call out:
-
-
// chain( func )
-
// make func chainable by making it return itsReturnValue||this
-
function chain( func )
-
{
-
return function()
-
{
-
return func.apply( this, arguments )||this;
-
}
-
}
-
-
-
// initialize everything
-
onload = function()
-
{
-
// initialize the contexts and the fractal
-
window.fx =
-
{
-
'barCtx': document.getElementById('bar' ).getContext('2d'),
-
'fooCtx': document.getElementById('foo' ).getContext('2d'),
-
'logicCtx': document.getElementById('logic' ).getContext('2d'),
-
'renderCtx': document.getElementById('render').getContext('2d'),
-
'fractal': [0,0,0,0,2,0,0,0,0],
-
CanvasRenderingContext2D: (window.CanvasRenderingContext2D?CanvasRenderingContext2D.prototype:document.getElementById('bar' ).getContext('2d').__proto__)
-
}
-
-
// set( what, to )
-
// sets a property of the CanvasRenderingContext2D, making such operation chainable
-
window.fx.CanvasRenderingContext2D.set = function( what, to )
-
{
-
this[what] = to;
-
}
-
-
// switchTo( context )
-
// return another CanvasRenderingContext2D, making such operation chainable
-
window.fx.CanvasRenderingContext2D.switchTo = function( context )
-
{
-
return context;
-
}
-
-
// chain a bunch of CanvasRenderingContext2D methods
-
for( chainThat in {set:1,switchTo:1,clearRect:1,save:1,translate:1,rotate:1,drawImage:1,scale:1,restore:1,fillRect:1,moveTo:1,lineTo:1,beginPath:1,closePath:1,stroke:1,fill:1,arc:1} )
-
{
-
window.fx.CanvasRenderingContext2D[chainThat] = chain( window.fx.CanvasRenderingContext2D[chainThat] );
-
}
-
-
// let's get the party started
-
render();
-
}
-
-
-
// render()
-
function render()
-
{
-
// the time is now
-
var now = new Date().getTime();
-
-
// mutate the outer cells of the rug
-
fx
-
.fractal[ Math.floor(Math.random()*8+5)%9 ] = Math.floor( Math.random()*3 );
-
-
// softly kills the previous generations of the rug
-
fx
-
.fooCtx
-
.set( 'fillStyle', 'rgba(0,0,0,.1)' )
-
.fillRect( 0, 0, 192, 192 )
-
.set( 'fillStyle', '#653' )
-
.switchTo( fx.barCtx )
-
.clearRect( 0, 0, 192, 192 );
-
-
// render 1st generation of the rug
-
for( var i=-1; i<9; fx.fooCtx.fillRect( (++i%3)*64+1,Math.floor(i/3)*64+1,(fx.fractal[i]&1)*62,(fx.fractal[i]&1)*62 ))
-
{
-
}
-
// render next generations of the rug
-
for( var j=0; j++<3; fx.fooCtx.drawImage( fx.barCtx.canvas,0,0 ) )
-
{
-
for( var i=-1; ++i<9; fx.barCtx.drawImage( fx.fooCtx.canvas,0,0,192,192, (i%3)*64+1,Math.floor(i/3)*64+1, (fx.fractal[i]&2)*31, (fx.fractal[i]&2)*31 ) )
-
{
-
}
-
}
-
-
// render rotozoomed rug
-
fx
-
.logicCtx
-
.set( 'globalCompositeOperation', 'source-over' )
-
.clearRect( 0, 0, 256, 192 )
-
.save()
-
.translate( 96, 96 )
-
.rotate( (now/5841%2)*Math.PI )
-
.scale( 1+2*((now/1274)%1), 1+2*((now/1274)%1) )
-
.drawImage( fx.fooCtx.canvas,0,0,192,192, -288,-288,576,576 )
-
.drawImage( fx.fooCtx.canvas,0,0,192,192, -96 ,-96 ,192,192 )
-
.drawImage( fx.fooCtx.canvas,0,0,192,192, -32 ,-32 ,64 ,64 )
-
.restore()
-
.set( 'globalCompositeOperation', 'copy' )
-
// prepare for hypnoglow
-
.switchTo( fx.renderCtx )
-
.set( 'globalCompositeOperation', 'source-over' )
-
.clearRect( 0, 0, 192, 192 )
-
.drawImage( fx.logicCtx.canvas, 0, 0 )
-
.set( 'globalCompositeOperation', 'lighter' );
-
-
// hypnoglow
-
for( var i=-1; ++i<6; fx.renderCtx.drawImage( fx.logicCtx.drawImage( fx.logicCtx.canvas, 0, 0, 192>>i, 192>>i, 0, 0, 96>>i, 96>>i ).canvas, 0, 0, 96>>i, 96>>i, 0, 0, 192, 192 ) )
-
{
-
}
-
-
// here we go again
-
setTimeout( render, 25 );
-
}
-
Related Content:











“P01″ is a madman as you can see (and he works for a browser vendor too :D). His site: http://p01.org/ has a collection of cool DHTML experiments, 256-byte entries and so on.
And I chose this month’s topic :D
p01has been coding intense, efficient visualizations for years, I have been watching his work since the late 90s in the demoscene. If you’re ever lacking inspiration, whether artistically, musically, or for coding, check out a few demoscene entries! Incredible works that push the envelope in every platform. I would not be the same without it.I made myself a start page with this code. I hope the author does not mind. Check it out here:
http://floatsolutions.com/docs/start/startpage.html
Thanks everyone.
Dion: o_O what did you do with the screenshot, it’s completely borked.
math0ne: Glad you like the effect this much. As long as you keep the credits clear and link back to the original page, I’m fine with it.
@mathOne: wow that’s awful.
This is really cool though. I love JavaScript — the language that lets you turn 112 lines into 20.
I covered Mathieu’s Cavas chaining trick in my blog. In a comment there, Mathieu replied that he came up with the idea on his own (and it’s a great one).
http://dreaminginjavascript.wordpress.com/2008/06/30/chainchainchain/