Dissecting the IE9 Fish Tank demo: PNG based sprite sheet animation with Canvas

FishIE tank

One of my favorite demos from the IE9 Test Drive site is FishIE Tank. Labeled a “Speed Demo” the FishIE Tank demonstrates hardware acceleration, canvas based image manipulation and PNG based sprite sheet animation. And watching the FPS meter on the side of the demo, with 500 fish on a wide screen monitor it still reads ~32 FPS, almost 60 fps with 250 fish. That’s worth taking a look at the code to see how its done.

I decided to recreate the demo to understand the code better.  This first part covers only the background image rendering and the sprite sheet animation.  Plus I’ve switched out the image and sprite sheet to something a little more unique.

Spinning Heads Part1

Run the first Spinning Heads demo
(for the best results run it in the IE9 Preview, Chrome isn’t too bad, Firefox is not so good)

Of course since this is just HTML, JavaScript and Canvas you can View Source and read the commented code to figure out how the demo works.  To save you some time, though, I’ll highlight the setup and the two main features.

Two canvas layers created during SetupSpinning Heads Part1 Diagram

When the page loads, the setup function is called and two canvas elements are created and added to the page. Pointers to the drawing context are then saved for reuse during the drawBackground and draw functions.  With CSS, the spriteCanvas is absolutely positioned so the heads appear over the background.

Drawing the background image

On load and when the window is resized the drawBackground function is called:

The main thing to point out here is the flip variable used to mirror every other background tile to create a smoother horizontally repeating background image, no matter what image is used. Vertically the image is stretched to match the height of the window.

Drawing the Sprites

During the setup, the sprites or Head objects in the case, are created with the createHeads function. A loop is then created using the setInterval function to call the draw function every 36 milliseconds. During the draw function each Head object is told to spin, effectively moving the next step through the sprite sheet.

Important to note here that in the draw method, if the context is not cleared first, artifacts from previous “frames” will remain. This is not a retained mode graphics system, we’re just creating a big set of pixels that all share the same layer.

The next bit of code to call out here is within the spin method a call to save() and restore() is used to manually add and remove the translate and scale transforms.  This way the transforms are unique to each Head.  Otherwise the transforms by default are cumulative and each successive Head would be moved further and further off the screen.  This is similiar to pushMatrix and popMatrix in Processing.

And finally the real magic, each successive draw call increments (or decrements when going in reverse) the cell variable which offsets the drawImage call so that the appropriate section of the sprite sheet is called.

So that’s it for the basics! If you’re familiar with procedural based animation the techniques should look pretty familiar to you. The biggest difference here is that there’s no plug-in or applet, just JavaScript and a modern browser.

This entry was posted in Client Technologies, Tutorials and tagged , , , , , . Bookmark the permalink.

9 Responses to Dissecting the IE9 Fish Tank demo: PNG based sprite sheet animation with Canvas

  1. Adam Porter says:

    Ooh, fun! Easter Island meets the Twilight Zone.

  2. Jesse says:

    Very nice! Do you think it will run on the HTML5 monster that is the Ipad : )

  3. Adam Kinney says:

    Yes, it runs on my iPhone running iOS4, so I’m guessing it should work on the iPad. Of course on the phone it runs noticably slower , but that’s not too big of a suprise considering the hardware.

  4. Jesse says:

    It actually seems to run faster on the iphone 4 than the ipad. A little bit anyhow.. Would love to be able to be able to make apps without submitting to the marketplace, hopefully the performance will get there.

  5. Meni says:

    Disclaimer: I’m an open-source, open-standards fanboi.

    Question: before you heard of IE9’s support for HTML5, would you have written an article like this? In other words, was WAS your opinion about HTML5 back then.

    Also, talking FPS and dissing other browsers on performance ground is lame and misses the point. First, when is Microsoft planning support for HTML5 in mobile? Second, how will performance be on netbooks? Instead I think you should emphasize cross browser and cross platform interoperability, that IS big news coming from Microsoft. I just want Silverlight fanboys to acknowledge something has just happened.

  6. Adam Kinney says:

    No, I didn’t start looking at HTML5 seriously until recently. I was always looking forward to it and trying to keep with it, but now that its support is growing and I’ve had some time to check it out, I’m happy I did. I started out as a HTML, CSS, JavaScript guy and am glad to see the new features along with Canvas and SVG.

    Regarding the comments about the other browsers, my main purpose in doing so is I was guessing most people would try it first in Chrome or Firefox and I wanted to let them know what to expect. My guess is it has to do with the hardware acceleration of the transparent PNGs.

    I acknowledge the goodness of cross browser and cross platform interoperability. I think its big news and its just about to happen.

  7. BR says:

    Thanks for posting this. I have had one problem. My page has regular HTML that I’d like rendered over the top of the canvas. So I changed one line of code to:

    document.body.insertBefore(tempCtx, document.body.lastChild);

    so that the canvas is inserted before the lastChild rather than before the firstChild. But now I can’t see my canvas. Is there some way to get a canvas showing underneath my other HTML elements?

    thanks

  8. Adam Kinney says:

    @BR: Layering a canvas element is just like layering other HTML elements, it sounds like you need to make sure that z-index and position attributes are set properly in CSS.

  9. Pingback: IE9 in Windows Phone will be good for cross-platform JavaScript and HTML5 apps « Tim Anderson’s ITWriting

Leave a Reply