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

Friday, 2 December 2011

Javascript/jQuery marquee

Here's something I want to keep for later, but other people may find useful too.  Feel free to do whatever you want with the source.  If it gets used anywhere then I'd like it if you'd post a URL so I can see it in action elsewhere, but you don't have to.

http://www.johnmolyneux.co.uk/examples/scrollbox.html



Friday, 4 March 2011

How to disable a button when clicked, but still postback (C#/ASP.Net)

If you want to stop a user from clicking a button twice on a web page you can simply disable it when clicked. This can be done by adding the following code to the OnClientClick property of the button...

this.disabled=true;

The problem with this is that it stops the button actually causing a postback event, therefore not triggering any server-side code.

I looked into various methods to solve this niggle, but they all involved client-side script, which I was trying to avoid and therefore avoid the mire that is cross-platform compatibility. I then came across a method of adding client events to controls at the server, and this is working beautifully. I expanded it into a fully working recursive method that you can call from Page_Load to effect this change on all buttons on a page.

Just paste this method into your page...


private void DisableButtonsOnClick(Control control)
{
    if (control is Button)
    {
        (control as Button).Attributes.Add("onclick",
            "this.disabled=true;" +
            Page.ClientScript.GetPostBackEventReference(control, "").ToString());
    }
    else if (control.HasControls())
    {
        foreach (Control child in control.Controls)
        {
            DisableButtonsOnClick(child);
        }
    }
}
Then, simply call
DisableButtonsOnClick(this);
in your Page_Load event.