Monday, July 03, 2006

DIVs are the source of cool for Javascript

Back in the day people were obsessing about how to shave off a few clock cycles in their rotozooming effect written in pure assembler. You can understand why I feel a bit giggly when someone is fussing about how #000 is so much more smaller and more efficient in CSS than #000000. We have come a long way -- now it is not even possible to write a smooth rotozoomer that works in browsers in a compatible way (there is a trick for that on IE though). We just have to forget about that sort of effects. One sort of pixel-setting which is allowed though are horizlines, continuous horizontal spans of pixels. These are relatively fast to do since they can be simulated with DIVs. What can you make with horizlines? Polygons! In other words you can make 3D. It will be quite slow, so you can only use a very limited amount of faces, but a cube at least is still doable.

If you squint, you can see that it just consists of many horizontal lines. And you can create a horizontal line with a simple <DIV> tag. Use CSS to set the width to what you want, make the position absolute and set it on the screen where you want using the left and top styles. For the color, you can use the background style. Of course a single horizontal line will get you nowhere, so you need to have many of them. In the image displayed above there are around 500 of them. To create movement, javascript is used to calculate where they should be and the styles are modified on the fly. Pretty perverse, really. The inefficiency compared to assembler is mind boggling, but hey it works (mostly).

To create anything remotely cool, you want things moving. And to get things moving, you need to know how to modify styles in runtime. To do this, you first set a javascript timer to call a function say every 20 milliseconds. The setInterval function can be used to do this, as you surely already know. So you do setInterval("tick()", 20) for example, and then your tick function will be called 50 times per second. Inside this tick function then you do your magic and shuffle the pre-created DIVs around.

Okay, this set you wondering about how to precreate the DIVs. I feel sorry for even mentioning that, since now I will have to explain that as well. You could only create the DIVs as you need them and destroy them afterwards, but that would be slow since you would be altering the DOM tens of thousands of times every second. A better way is to just create those DIVs in the beginning. Just use document.createElement("DIV") in a loop.

        // First create a cache of horizlines
var i;
for (i=0; i<cnt; i++) {
hors[i] = document.createElement("div");
hors[i].style['position'] = "absolute";
hors[i].style['top'] = 0;
hors[i].style['left'] = 0;
hors[i].style['width'] = 0;
hors[i].style['height'] = 0;
hors[i].style['backgroundColor'] = "#000000";
document.body.insertBefore(hors[i], document.body.lastChild);

I will not go into any more details now, but suffice to say that inside your tick() function you can then reference the hors array and change the positions using hors[x].style['left'] = 400; for example. If some hors are unnecessary, just use the visibility style to set them to hidden or move them to a negative vertical position so that they will not be visible. Now all you need is some junior high school level math to create a cube out of them. Search the net for "triangle filler" to see how to do that.