Tuesday 13 December 2011

Create an animated PNG from a sequence of images using jQuery

As the title says, with this script you can create an animated effect with a sequence of PNGs. Why would you do this? Simply so you can have 32-bit images, rather than 8-bit GIFs with 1-bit transparency.


function animateImage(Index) {
    $("img.animated:eq(" + Index + ")").each(function (Index) {
        if (!$(this).is(":visible")) {
            var intervalID = parseInt($(this).attr("intervalid"));
            clearInterval(intervalID);
        } else {
            var max = parseInt($(this).attr("max"));
            var pattern = $(this).attr("pattern");
            var index = parseInt($(this).attr("index"));
            index++;
            if (index > max) {
                index = 1;
            }
            var src = pattern.replace("#", index);
            $(this).attr("index", index);
            $(this).attr("src", src);
        }
    });
}

function initialiseAnimatedImages() {
    $("img.animated").each(function (Index) {
        var interval = $(this).attr("interval");
        $(this).attr("index", "0");
        var intervalID = setInterval(function () { animateImage(Index); }, interval);
        $(this).attr("intervalid", intervalID);
    });
}

$(document).ready(function () {
    initialiseAnimatedImages();
});
Simply include the above script in your page(s) and where you want to specify an animated image (doesn't have to be PNG) then do the following...


<img class="animated" interval="50" max="20" pattern="./images/image-sequence-#.png" />

Pattern is the image URL, but # will be replaced with a number between 1 and max.  Interval is the time between changing from image 1 to 2, 2 to 3 etc. in milliseconds.  So, an interval of 50 will give you about 20 frames per second.  (I say "about" because browsers are not exact and they all vary slightly).  Make sure the class is or includes "animated" so that the script knows to animate it.  (In case you didn't know, you can mix classes, such as "myclass animated".)



The only other thing added is that if you set the image to be invisible, the animation will stop.  This may sound a little odd, but your browser would still be taking up CPU animating the image, even when invisible.  This avoids it.


Anyway, there was a reason that I made this (other than animated GIFs being ugly).  I wanted to make a "loading" style spinner animation that you could change the colour of using CSS.


An example of this can be seen here....


http://www.johnmolyneux.co.uk/examples/loading-spinner.html

11 comments:

  1. Very nice ans usefull script !
    I have a question :
    Is it possible to play the sequence only one time ?
    thx

    ReplyDelete
  2. Nice!
    Do you know how to stop it?

    ReplyDelete
  3. To stop it, remove var from the line where intervalID is declared so that it becomes a window variable, and then just use clearInterval(intervalID);

    ReplyDelete
  4. Dear John,

    Would you know how this code might be modified so as to allow the user to pause, stop, and play the animation?

    ReplyDelete
  5. Just pause/stop an animation, use the following function...

    function pauseAnimatedImages() {
    $("img.animated").each(function () {
    clearInterval(parseInt($(this).attr("interval"), 10));
    });
    }

    To start it again just call initialiseAnimatedImages(); again. I'm writing a plugin called "spritimation" which will allow you to create an animated image from a sprite, so you'd have all the frames in 1 image. When I've done this I'll post a link to github on here :)

    ReplyDelete
  6. Hi.

    Is it possible to run the animation once and the stop it at the last slide ?

    Thanks.

    ReplyDelete
    Replies
    1. Yes, that's just a small change. Where it checks if (index > max), change that if statement to this...

      if (index == max) {
      var intervalID = parseInt($(this).attr("intervalid"));
      clearInterval(intervalID);
      }

      That will stop the timer on the last frame, which will stop the animation.

      Delete
  7. I just wanted to say thanks for making this! Very very useful, and I appreciate it!

    ReplyDelete
    Replies
    1. Thanks for letting me know. It's always nice to know when something's come in useful :)

      Delete
  8. Hi John,

    I have used this script working fine chrome and safari but flickering issue in Firefox. can you guide us to all.

    Regards,
    Balaji B.

    ReplyDelete
    Replies
    1. Hi Anitha,

      I've not tried it in Firefox myself, so I'll have a play about and see what I can find out for you :)

      Delete