open in new window

Demos : Mandelbrot

Code:

<html>
<head>
     <script type="text/javascript" src="//lib.ivank.net/ivank.js"></script>
     <script type="text/javascript">
          /*	
               This demo is so cool, because it is all computed by JavaScript on CPU!
               There is no Fragment Shader for it. 
               Click on area to zoom in.
          */
          
          var stage, bd, bm, down=false, zoom=1, zoomX=0, zoomY=0, paused=false;
          var w=512,h=512,S=0, LIM=65;       // bitmap size in pixels
          var OX=-2,SX=2.5,OY=-1.25,SY=2.5;  // interval of the rendered set
          
          var plte = [
               990786,1315373,1705753,2360337,3080457,3932678,4785156,5637378,
               6555392,7805190,9055244,10305298,11620888,12674856,13729081,14391647,
               15054214,15650988,16313555,14412514,12577265,9427444,6277624,3127803,
               43775,38373,32972,27570,22425,83329,210026,600406];
               
          function Start() {
               stage = new Stage("c");
               
               var sw=stage.stageWidth, sh=stage.stageHeight;  //w=sw;  h=sh;
               if(sw>sh) {  h=~~(w*sh/sw);  SX=2.5*sw/sh;  OX=-2   -1.25*(sw/sh-1);  }
               else      {  w=~~(h*sw/sh);  SY=2.5*sh/sw;  OY=-1.25-1.25*(sh/sw-1);  }
               S=h>>>6;
               
               bd = BitmapData.empty(w, h, 0xff000000);
               
               bm = new Bitmap(bd);
               bm.scaleX = sw/w;  bm.scaleY = sh/h;
               stage.addChild(bm);
               
               stage.addEventListener(Event.ENTER_FRAME, drawMandelbrot);
               stage.addEventListener(MouseEvent.MOUSE_DOWN, function(e){down=true ;});
               stage.addEventListener(MouseEvent.MOUSE_UP  , function(e){down=false;});
               stage.addEventListener(KeyboardEvent.KEY_UP , function(e){if(e.keyCode==32) paused=!paused;});
          }
          
          function drawMandelbrot() {			
               var mox = bm.mouseX, moy = bm.mouseY, psd=paused;
               if(bm.mouseY>h*0.93 && down) {  LIM = Math.round(300*mox/w);  psd=true;  }
               else if(!paused) {
                    var msx = mox/w, msy = moy/h;
                    var mx = zoomX + msx/zoom, my = zoomY + msy/zoom;
                    
                    zoom = down ? zoom*1.05 : Math.max(1, zoom/1.05);			
                    zoomX = Math.max(0, Math.min(1-1/zoom, mx - msx/zoom));
                    zoomY = Math.max(0, Math.min(1-1/zoom, my - msy/zoom));
               }
               var xc = 1 / (w*zoom), yc = 1 / (h*zoom);
               
               var top = new Uint8Array(w+1);
               for(var y=0; y<h; y++) {	// rows
                    var cy = OY + SY*(zoomY + y*yc);
                    for(var x=0; x<w; x+=2) {	// columns
                    	if(y>h-S) {
                    		var c = (x<w*(LIM/300)) ? (psd?0x0000ff:0) : 0xffffff;
                    		bd.setPixel(x,y,c);  bd.setPixel(x+1,y,c);  continue;  
                    	}
                    	var i0=0, i1 = mandIter(OX + SX*(zoomX + (x+1)*xc),cy);
                    	
                    	// if left, right and top are the same
                    	if(x!=0 && top[x-1]==i1 && i1==top[x]) i0=i1;   else
                    	i0 = mandIter(OX + SX*(zoomX + x*xc),cy);
                    	
                    	setColor(x,y,i0);  setColor(x+1,y,i1);
                    	top[x]=i0;  top[x+1]=i1;
                    }
               }
          }
          
          function setColor(x,y,i) { bd.setPixel(x,y, (i<3||i==LIM) ? 0 : plte[i&31]  );  }
          
          function mandIter(x0,y0) {
               var x2=0, y2=0;
               var x=0, y=0, i=0;
               while(x2+y2<4 && ++i<LIM) {
                    y = (x+x) * y + y0;
                    x = x2 - y2 + x0;
                    x2= x * x;
                    y2= y * y;
               }
               return i;
          }
     </script>
</head>
<body onload="Start();"><canvas id="c"></canvas></body>
</html>