Wednesday, June 18th, 2008

Hypno trip down the fractal rug

Category: Canvas, JavaScript

Hypno trip

What a great title. It is an entry in the JavaScript 20 liners call out:

javascript

  1. //  chain( func )
  2. //  make func chainable by making it return itsReturnValue||this
  3. function chain( func )
  4. {
  5.     return function()
  6.     {
  7.         return func.apply( this, arguments )||this;
  8.     }
  9. }
  10.  
  11.  
  12. //  initialize everything
  13. onload = function()
  14. {
  15.     //  initialize the contexts and the fractal
  16.     window.fx =
  17.     {
  18.         'barCtx':       document.getElementById('bar'   ).getContext('2d'),
  19.         'fooCtx':       document.getElementById('foo'   ).getContext('2d'),
  20.         'logicCtx':     document.getElementById('logic' ).getContext('2d'),
  21.         'renderCtx':    document.getElementById('render').getContext('2d'),
  22.         'fractal':      [0,0,0,0,2,0,0,0,0],
  23.         CanvasRenderingContext2D:   (window.CanvasRenderingContext2D?CanvasRenderingContext2D.prototype:document.getElementById('bar'   ).getContext('2d').__proto__)
  24.     }
  25.  
  26.     //  set( what, to )
  27.     //  sets a property of the CanvasRenderingContext2D, making such operation chainable
  28.     window.fx.CanvasRenderingContext2D.set = function( what, to )
  29.     {
  30.         this[what] = to;
  31.     }
  32.  
  33.     //  switchTo( context )
  34.     //  return another CanvasRenderingContext2D, making such operation chainable
  35.     window.fx.CanvasRenderingContext2D.switchTo = function( context )
  36.     {
  37.         return context;
  38.     }
  39.  
  40.     //  chain a bunch of CanvasRenderingContext2D methods
  41.     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} )
  42.     {
  43.         window.fx.CanvasRenderingContext2D[chainThat] = chain( window.fx.CanvasRenderingContext2D[chainThat] );
  44.     }
  45.  
  46.     //  let's get the party started
  47.     render();
  48. }
  49.  
  50.  
  51. //  render()
  52. function render()
  53. {
  54.     //  the time is now
  55.     var now     = new Date().getTime();
  56.  
  57.     //  mutate the outer cells of the rug
  58.     fx
  59.         .fractal[ Math.floor(Math.random()*8+5)%9 ] = Math.floor( Math.random()*3 );
  60.  
  61.     //  softly kills the previous generations of the rug
  62.     fx
  63.         .fooCtx
  64.             .set( 'fillStyle', 'rgba(0,0,0,.1)' )
  65.             .fillRect( 0, 0, 192, 192 )
  66.             .set( 'fillStyle', '#653' )
  67.         .switchTo( fx.barCtx )
  68.             .clearRect( 0, 0, 192, 192 );
  69.  
  70.     //  render 1st generation of the rug
  71.     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 ))
  72.     {
  73.     }
  74.     //  render next generations of the rug
  75.     for( var j=0; j++<3; fx.fooCtx.drawImage( fx.barCtx.canvas,0,0 ) )
  76.     {
  77.         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 ) )
  78.         {
  79.         }
  80.     }
  81.  
  82.     //  render rotozoomed rug
  83.     fx
  84.         .logicCtx
  85.             .set( 'globalCompositeOperation', 'source-over' )
  86.             .clearRect( 0, 0, 256, 192 )
  87.             .save()
  88.             .translate( 96, 96 )
  89.             .rotate( (now/5841%2)*Math.PI )
  90.             .scale( 1+2*((now/1274)%1), 1+2*((now/1274)%1) )
  91.             .drawImage( fx.fooCtx.canvas,0,0,192,192, -288,-288,576,576 )
  92.             .drawImage( fx.fooCtx.canvas,0,0,192,192, -96 ,-96 ,192,192 )
  93.             .drawImage( fx.fooCtx.canvas,0,0,192,192, -32 ,-32 ,64 ,64  )
  94.             .restore()
  95.             .set( 'globalCompositeOperation', 'copy' )
  96.         //  prepare for hypnoglow
  97.         .switchTo( fx.renderCtx )
  98.             .set( 'globalCompositeOperation', 'source-over' )
  99.             .clearRect( 0, 0, 192, 192 )
  100.             .drawImage( fx.logicCtx.canvas, 0, 0 )
  101.             .set( 'globalCompositeOperation', 'lighter' );
  102.  
  103.     //  hypnoglow
  104.     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 ) )
  105.     {
  106.     }
  107.  
  108.     //  here we go again
  109.     setTimeout( render, 25 );
  110. }

Posted by Dion Almaer at 6:32 am
7 Comments

++++-
4.4 rating from 37 votes

7 Comments »

Comments feed TrackBack URI

“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.

Comment by Schill — June 18, 2008

And I chose this month’s topic :D

Comment by KevinWeibell — June 18, 2008

p01 has 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.

Comment by doublerebel — June 18, 2008

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

Comment by math0ne — June 18, 2008

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.

Comment by Mathieu \'p01\' Henri — June 19, 2008

@mathOne: wow that’s awful.

This is really cool though. I love JavaScript — the language that lets you turn 112 lines into 20.

Comment by richtaur — June 22, 2008

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/

Comment by Nosredna — June 30, 2008

Leave a comment

You must be logged in to post a comment.