Source for demo by Jonathan Brodsky.
C=document.body.children[0];C.innerHTML="<style>*{margin:0;width:100%;height:100%;overflow:hidden;}</style>";a=C.width=w=191;h=C.height=w*innerHeight/innerWidth|0;var ctx=C.getContext("2d");var BD=ctx.createImageData(w,h);var MD=ctx.createImageData(w,h);var M=Array();E=ctx.createRadialGradient(w/2,h/2,0,w/2,h/2,h);E[g="addColorStop"](0.3,"#200");E[g](0.7,"#500");E[g](1,"#fff");ctx.fillStyle=E;ctx.fillRect(0,0,w,h);BD=ctx.getImageData(0,0,w,h);var k=0;for(j=0;j<h;j++){y=-1+2*j/h;for(i=0;i<w;i++){x=-1+2*i/w;d=Math.sqrt(x*x+y*y);a=Math.atan2(y,x);r=d;u=(0.02*y+0.03)*Math.cos(a*3)/r;v=(0.02*y+0.03)*Math.sin(a*3)/r;M[k++]=w*u&w-1;M[k++]=h*v&h-1;}}var cycle=0;setInterval(function(){cycle++;for(var b=0;b<BD[d="data"][l="length"]/4;b++){u=M[b+0]+cycle;v=M[b+1]+cycle;f=b*4;MD.data[f+0]=BD[d][((w*v+u)*4+0)%BD[d][l]];MD.data[f+1]=BD[d][((w*v+u)*4+1)%BD[d][l]];MD.data[f+2]=BD[d][((w*v+u)*4+2)%BD[d][l]];MD.data[f+3]=255}ctx.putImageData(MD,0,0)},25);