Activate your free membership today | Log-in

Monday, December 17th, 2007

3D-style animation in JavaScript

Category: 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:

HTML:
  1.  
  2. <img id="slice-0" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAABACAIAAABUc4oXAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAewwAAHsMBvJeX2gAAACFJREFUCNdj+P//PxMDAwPd8INH75nw2Mnw/ftvBjq6CQDNIw8MeLLR3AAAAABJRU5ErkJggg=="/>
  3. <img id="slice-1" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAABACAIAAABUc4oXAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlvRkZzAAAAAQAAAAAAEXZlawAAAAlwSFlzAAAewwAAHsMBvJeX2gAAAEpJREFUCNdj+P//PxMDAwNN8PsP35lOnn3MdOzUQ6brN18xvXrzlenJs49M+OwUE+Vh4uZiZbI2V2DSUBVluHPvDcO/f/8YaOROAMXBIDUsb8h5AAAAAElFTkSuQmCC"/>
  4.  

and then you put them all together via JavaScript:

JAVASCRIPT:
  1.  
  2.         // Draw a frame
  3.         function draw(x) {
  4.                 var prevx=0;
  5.                 for (i=0;i&lt;384;i++) {
  6.                         var rad = i*3.14/384;
  7.                         var nextx = Math.round((1-Math.cos(rad))*180);
  8.                         var h=Math.round(40+50*Math.sin(rad));
  9.                         var s = document.getElementById("slice-"+((i+x*2)%384));
  10.                         s.height=h;
  11.                         var w = Math.round(nextx-prevx);
  12.                         if (w==0) {
  13.                                 s.style.display="none";
  14.                         } else {               
  15.                                 s.style.display="block";
  16.                                 s.width= w;
  17.                                 s.style.top=""+(50-Math.round(h/1.5))+"px";
  18.                                 s.style.left=""+(prevx)+"px";
  19.                         }
  20.                         prevx=nextx;
  21.                 }
  22.         }
  23.        
  24.         // Animate the images
  25.         var frame=0;
  26.         function animate() {
  27.                 draw(frame++);
  28.                 setTimeout("animate()",1);
  29.         }
  30.  
  31.         // Initialize the image slices
  32.         for (i=0;i&lt;384;i++) {
  33.                 var s = document.getElementById("slice-"+i);
  34.                 s.style.position="absolute";
  35.                 s.style.display="none";
  36.         }
  37.         animate();
  38.  

Then sit and watch the animation.

jsanimate

Posted by Dion Almaer at 5:23 am

++---
2.8 rating from 50 votes

9 Comments »

Comments feed TrackBack URI

Listen to that CPU fan roar! 8-)

Comment by RichieHindle — December 17, 2007

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.

Comment by Mathieu \'p01\' Henri — December 17, 2007

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.

Comment by Joonas Lehtinen — December 17, 2007

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 ;)

Comment by OndraM — December 17, 2007

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. ;)

Comment by Schill — December 17, 2007

“probably XHTML 8″

Eh. I’m holding out hope it’ll be in LMNOPHTML2.

Comment by Trevor — December 17, 2007

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.

Comment by Joonas Lehtinen — December 18, 2007

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.

Comment by LlamaGuy — January 5, 2008

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.

Comment by LookingSoftware — April 19, 2008

Leave a comment

You must be logged in to post a comment.