One of the issues with gif animations is being able to stop and start them at will. This post examines a method of using javascript to control CSS Sprites for Animation.
We’re going to show how one can create the following animation using javascript and sprites and what benefits you might receive:
The gist of this method is to use css background images, which are swapped out via javascript to show and control the animation. In a filesize test using an animation with 9 frames, the sprites actually require less memory than a comparable animated gif:
File | Size | Description |
---|---|---|
Individual frames as separate PNG’s | 95421 | Baseline — this is the sum of the sizes of the 9 frame files. |
anim.gif | 43463 | Animated gif version |
knot.png | 81701 | 24 bit PNG, sprites. Notice that this is smaller than the sum of the 9 files, but quite larger than the animated gif. |
knot-grey.png | 49708 | Greyscale version of the png sprites. This is much smaller and approaches the size of the gif animation. |
knot.gif | 40853 | Gif version of the sprites. This is smaller than the anmated version. |
knot-idx.png | 38281 | Indexed version of the png sprites. Smallest yet. |
I think that between the added control, decreased number of files to download (a single file containing sprites can be used in many places), and the potential for reduced file size, that this is a viable method for producing animations.
The javascript code is library agnostic. Had I tied it to one library or another, I could have made it shorter, but I think that the benefits of being agnostic outweigh the potential byte savings.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
// Except as otherwise noted, the following code is copyright 2008, 2009 // by Matthew Williams // // Usage and description of the script may be found at: // http://matthewkwilliams.com/ // // In order to use it, you need the following: // + A sprite file // + CSS entries for the locations of the sprites. // These are named FOO-frame-n where foo is the name of the animation, // and n is the frame. // + A block entity in which the animation will be placed. // This entity needs the following css rules since we're using the css // background trick: // + width // + height // // + A sample use would be as follows: // <script src="sprite-animator.js" type="text/javascript"><!--mce:0--></script> // // <script type="text/javascript"><!--mce:1--></script> // <button onclick="gearanim.start(); return false;">Start</button> // <button onclick="gearanim.stop(); return false;">Stop</button> // This object does the updating of the sprite animation function SpriteUpdater(instance) { var obj = instance; this.updateSprite = function() { var elem = document.getElementById(obj.id + '-sprite-container'); var a = elem.className.split('-'); var num = parseInt(a[a.length - 1]); var newNum = num; if (num >= obj.numFrames) { newNum = obj.loop ? 1 : obj.numFrames; } else { newNum = newNum + 1; } if(newNum != num) elem.className = obj.id + '-frame-' + newNum; else clearInterval(obj.intervalID); }; } // This object handles the animation // + id = the id of the block // + file = the file which contains the sprites // + loop = true/false whether it loops or not // + delay = what is the delay between frames? function SpriteAnimator(id, file, loop, delay) { // this function and the next are from css-toolbox.js // created by Patrick Hunlock :: http://www.hunlock.com // and originally found at the JavaScript Source: // http://javascript.internet.com function getCSSRule(ruleName, deleteFlag) { if (document.styleSheets) { for (var i=0; i '; element.innerHTML = insertion + element.innerHTML; }; // add css rules for the sprite container this.updateCSS = function() { var rule = addCSSRule('#' + this.id + '-sprite-container'); rule.style.backgroundImage = 'url("' + file + '")'; rule.style.backgroundRepeat = 'none'; rule.style.padding = '0'; rule.style.margin = '0'; rule.style.width = '100%'; rule.style.height = '100%'; }; // stop the animation this.stop = function() { if (this.intervalID != false) { clearInterval(this.intervalID); } }; // start the animation this.start = function(){ updater = new SpriteUpdater(this); this.intervalID = setInterval(updater.updateSprite,this.delay); }; this.id = id; this.file = file; this.loop = loop; this.delay = delay; this.updateHTML(); this.updateCSS(); this.numFrames = this.countFrames(); this.intervalID = false; } |
Sample CSS looks like this:
1 2 3 4 5 6 7 8 9 |
.knot-frame-1{background-position: 0px 0px;} .knot-frame-2{background-position: -138px 0px;} .knot-frame-3{background-position: -276px 0px;} .knot-frame-4{background-position: -414px 0px;} .knot-frame-5{background-position: -552px 0px;} .knot-frame-6{background-position: -690px 0px;} .knot-frame-7{background-position: -828px 0px;} .knot-frame-8{background-position: -966px 0px;} .knot-frame-9{background-position: -1104px 0px;} |
Here’s the javascript source file:
sprite-animator
3 comments
Thank you
December 10, 2009 at 4:23 am (UTC -5) Link to this comment
Thanks for this, was very helpful 🙂
Zach
July 23, 2010 at 11:09 pm (UTC -5) Link to this comment
Hey this page is EXACTLY what I’m looking for!!! I wan’t to do some Super Mario Bros. animations for my website selling super mario brothers toys and games, would you be able to help me a bit further with a project, I was having some trouble interpreting your code, as I’m a total n00b, but I’d love to have some help, as this is just what I need!
Thanks!!
Louise Lambert
September 28, 2010 at 11:27 am (UTC -5) Link to this comment
Great site. Keep up the good work.