Monday, December 17th, 2007
3D-style animation in JavaScript
Joonas Lehtinen of IT Mill has shown us something that we should probably never do. As a proof of concept he decided to see if it was "possible to do a 3D-style animation in plain JavaScript without Flash, SVG, Canvas or any other fancy stuff."
He ended up with a solution that:
- Slice a image in 1px wide slices
- Embed all the slides in the HTML using data-uris to avoid loading large number of images
- Move and scale image slices for each animation frame to create some nice effect
So, first you litter your HTML with:
-
-
<img id="slice-0" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAABACAIAAABUc4oXAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAewwAAHsMBvJeX2gAAACFJREFUCNdj+P//PxMDAwPd8INH75nw2Mnw/ftvBjq6CQDNIw8MeLLR3AAAAABJRU5ErkJggg=="/>
-
<img id="slice-1" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAABACAIAAABUc4oXAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlvRkZzAAAAAQAAAAAAEXZlawAAAAlwSFlzAAAewwAAHsMBvJeX2gAAAEpJREFUCNdj+P//PxMDAwNN8PsP35lOnn3MdOzUQ6brN18xvXrzlenJs49M+OwUE+Vh4uZiZbI2V2DSUBVluHPvDcO/f/8YaOROAMXBIDUsb8h5AAAAAElFTkSuQmCC"/>
-
and then you put them all together via JavaScript:
-
-
// Draw a frame
-
function draw(x) {
-
var prevx=0;
-
for (i=0;i<384;i++) {
-
var rad = i*3.14/384;
-
var nextx = Math.round((1-Math.cos(rad))*180);
-
var h=Math.round(40+50*Math.sin(rad));
-
var s = document.getElementById("slice-"+((i+x*2)%384));
-
s.height=h;
-
var w = Math.round(nextx-prevx);
-
if (w==0) {
-
s.style.display="none";
-
} else {
-
s.style.display="block";
-
s.width= w;
-
s.style.top=""+(50-Math.round(h/1.5))+"px";
-
s.style.left=""+(prevx)+"px";
-
}
-
prevx=nextx;
-
}
-
}
-
-
// Animate the images
-
var frame=0;
-
function animate() {
-
draw(frame++);
-
setTimeout("animate()",1);
-
}
-
-
// Initialize the image slices
-
for (i=0;i<384;i++) {
-
var s = document.getElementById("slice-"+i);
-
s.style.position="absolute";
-
s.style.display="none";
-
}
-
animate();
-
Then sit and watch the animation.













Listen to that CPU fan roar! 8-)
It’s not different than the dozens of raycasting engines that have been around for years. And the markup … *yikes*
Also, I loath animations that are based on an arbitrary counter instead of a timestamp.
setTimeout("animate()",1);should readsetTimeout(animate,1);There is no reason to trigger the JavaScript parser/interpreter just to call a function.Richie, I do hear some roar from my MacBook Pro ;)
This is an example on how NOT to do the animation, but how to waste electricity in most obscure manner. It is amazing to see that a modern dualcore CPU is not enough for a smooth 400×200px animation. Anyhow - I decided to blog this as it might inspire someone else to use raycasting-type “rendering” for some meaningful purpose.
while this is a nice hack, that has been also used for simulating 3D in flash, it is extremely resource consuming :(
I guess we will have to wait for some kind of OpenGL support in the rendering core…probably XHTML 8 ;)
An interesting JS demo, but I’ll echo p01’s comments. I’m surprised the image data wasn’t compressed, encoded in JS and then written out dynamically - though I understand that would be time-consuming to do. ;)
“probably XHTML 8″
Eh. I’m holding out hope it’ll be in LMNOPHTML2.
Schill, Image data is compressed as the individual slices are PNG, but of course including them as separate PNG:s instead of just one has a huge overhead.
Original PNG (384×64px) 6233 bytes, 384 slices totals 84350 bytes, All slices embedded to HTML as data-uris together with the javascript 145153 bytes, HTML compressed with gzip 19811 bytes
So in the end, if http compression is used, you end up with over 200% overhead for your image size (when comparing slice-animation html to original png). I would guess that the overhead would be a lot smaller if image was taller than 64px.
Couldn’t this be done without using slices by having the image in an over:hidden and using position:relative to only expose the slices you want? It may end up being faster because you would have images at once.
Good work.
I never known 3d animation can do with Java script before. With 3d animation, I use several software such as Flash, Xara, Blender. I think using software to do 3d animation is much easier and faster.