var d=document,g=d.body.style,i=d.getElementById("c"),k=i.width=300,l=i.height=innerHeight,m=i.getContext("2d");m.fillRect(0,0,k,l);for(var n=m.getImageData(0,0,k,l),o=n.data,p=Math.cos,q=0,r=[],s=[],u=0;u<l;){r[u]=k;s[u++]=0}g.textAlign="center";g.margin="0px";g.background="#000";g.overflow="hidden";function v(a,e,b,h,t){a=a+b*k<<2;e=e+b*k<<2;for(b=0;a<e;){o[a]=b<3?0:h|0;o[a+1]=o[a+2]=b++<3?0:t|0;a+=4}}setInterval(function(){q+=0.05;for(var a=0;a<l;a++){for(var e=k,b=0,h=k,t=q+4*p(q)*(a/l),j=0;j<=15;j++){var c=6.3*j/15,f=p(c);f=1-0.4*f*f;c=k+k*p(c+t)*f>>1;if(h<c){f=255*f^0;v(h,c,a,f,j%3?f:0)}h=c;e=c<e?c:e;b=c>b?c:b}v(r[a],e,a);v(b,s[a],a);r[a]=e;s[a]=b}m.putImageData(n,0,0)},30)
var doc = document;
var style = doc.body.style;
var canvas = doc.getElementById("c");
var width = canvas.width = 300;
var height = canvas.height = innerHeight;
// Paint the canvas opaque black (fillStyle should be "black" by default).
var ctx = canvas.getContext("2d");
ctx.fillRect(0, 0, width, height);
// The original approach was to draw horizontal lines using .fillRect(...).
// Explicitly setting the pixels turned out to be faster in this case.
var image = ctx.getImageData(0, 0, width, height);
var data = image.data;
var cos = Math.cos;
var PI2 = 6.3; // Eh, close enough to Math.PI * 2 ;)
var STEPS = 15;
var iteration = 0;
// Keep track of the min and max painted x coordinate for each
// horizontal line. This allows us to quickly clean up the painted
// pixels remaining from the previous iterations.
var yMin = [];
var yMax = [];
for (var i = 0; i < height;) {
yMin[i] = width;
yMax[i++] = 0;
}
style.textAlign = "center";
style.margin = "0px";
style.background = "#000";
style.overflow = "hidden";
// Draw a horizontal line with the first 3 pixels set to black.
function line(x1, x2, y, r, gb) {
// Using << 2 instead of * 4 allows the minifier to remove the
// parentheses (<< has lower a precedence than *), saving bytes.
x1 = (x1 + y * width) << 2;
x2 = (x2 + y * width) << 2;
// Reuse y as an iteration counter.
y = 0;
while (x1 < x2) {
// (undefined | 0) -> ToInt32(ToNumber(undefined)) -> 0.
// Therefore we can call line(x1, x2, y) with the rest of the
// arguments undefined when we want to draw a black line.
data[x1] = (y < 3) ? 0 : r | 0;
data[x1+1] = data[x1+2] = (y++ < 3) ? 0 : gb | 0;
x1 += 4;
}
}
function f() {
iteration += .05;
for (var y = 0; y < height; y++) {
var min = width;
var max = 0;
var previousX = width;
var twist = iteration + 4 * cos(iteration) * (y / height);
for (var step = 0; step <= STEPS; step++) {
var angle = PI2 * step / STEPS;
var radius = cos(angle);
radius = (1 - .4 * radius * radius);
// (num >> 2) -> (ToInt32(num) >> 2).
var x = (width + width * cos(angle + twist) * radius) >> 1;
if (previousX < x) {
// (num ^ 0) -> (ToInt32(num) ^ 0) -> ToInt32(num).
var r = (255 * radius) ^ 0;
line(previousX, x, y, r, (step % 3) ? r : 0);
}
previousX = x;
min = (x < min) ? x : min;
max = x > max ? x : max;
}
// Clear the painted pixels remaining from the previous iteration.
line(yMin[y], min, y);
line(max, yMax[y], y);
yMin[y] = min;
yMax[y] = max;
}
ctx.putImageData(image, 0, 0);
}
setInterval(f, 30);