Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

JavaScript Image Fader

4.79/5 (7 votes)
19 May 2012CPOL7 min read 69.1K   1.4K  
Fading multiple images using jQuery in JavaScript.

Introduction

"This code allows you to set up easy fading in and out of images on a web page. It is a common thing now to see columns of latest images on the sides of website pages. However, there is no code anywhere for actually doing the fading of images. So, in this article, that is what I present: some simple JavaScript code that can be incorporated into any website to fade images in and out." 

Since the first version of my article this is no longer true. As pointed out to me some while ago now, jQuery offers extremely good methods of animating objects, including fading images. So this new version of the article, which is probably a long time overdue, now uses jQuery to do the fading.

Update To jQuery

To update to the jQuery version of my code, simply download the files and then script references (in your web page's head tag) to the jQuery-1.7.2.min.js file and ImageFader_jQuery.min.js file. These are all you need (apart from some images and a web page) to use my code. The full version of the code with comments is also included in the download. 

Note: My code does not require the jQuery UI library.

Note: My code will most likely work with older versions of the jQuery library, though I strongly recommend you keep up-to-date. jQuery is very good at backward compatibility I have found so upgrading isn't an issue, just overwrite the jQuery JS file and your done. 

With the update to using jQuery the code now becomes reliably cross-browser compatible along with having better backward compatibility - in other words it works in IE7 and later reliably! Big Grin | <img src= " /> It is also has more accurate and reliable timing since jQuery does far better timing of delays and fading. Finally, jQuery gives simpler (once you understand jQuery syntax which isn't hard at all), shorter code meaning smaller downloads for your visitors and it is easier to modify my code. 

Using the Code 

The code can be used very simply. Add the provided ImageFader_jQuery.min.js file and jQuery-1.7.2.min.js in the head like any other script. In the old version you would have needed to add a handler for the onload event but as the code now uses jQuery, it automatically handles the ready event. 

Setting Up Images and Starting Fading 

So the first thing you'll want to do is set which images you're going to use. Well, this is done simply (and now more reliably too) in the two following steps. 

1. In the code, find the variable called ImagesFolderURL. Set this to the root relative URL of your images folder (use URL encoding). Do NOT include starting to trailing slashes. 

Note: For compatibility with Chrome and other browsers, all URL's must be URL encoded. 

2. Now find the ready event handler. It will look something like this: 

JavaScript
$(document).ready(function ()
{
    FileNames[FileNames.length] = ExtraPath + "Backgrounds/Carribean-Beach.jpg";
    FileNames[FileNames.length] = ExtraPath + "Backgrounds/Red-Dream-Swirls.jpg";
    FileNames[FileNames.length] = ExtraPath + "Backgrounds/Space.jpg";
    FileNames[FileNames.length] = ExtraPath + "Backgrounds/Swirls-Of-Fire.jpg";
    FileNames[FileNames.length] = ExtraPath + "Backgrounds/Purple-Starry-Hearts.jpg";
    FileNames[FileNames.length] = ExtraPath + "Backgrounds/Blue-Cells.jpg";
    FileNames[FileNames.length] = ExtraPath + "Backgrounds/Blue-Cells-2.jpg";
    FileNames[FileNames.length] = ExtraPath + "Backgrounds/water-008.jpg";

    //FadeImage(ElementId, Delay before starting first fade)
    FadeImage('Image1', 0);
    FadeImage('Image2', 1000);
    FadeImage('Image3', 2000);
    FadeImage('Image4', 3000);
}); 

So this event handler does two things. It adds all the paths of the Images to the list of file names and it starts the images fading. Looking at setting file names first, you should use the following line of code swap in your image's URLs (URLs are relative to your Images folder that you set above). 

JavaScript
FileNames[FileNames.length] = ExtraPath + "Backgrounds/Carribean-Beach.jpg"; 

Now to set images fading simply add/replace the FadeImage calls in the ready event handler at the bottom. 

FadeImage(/*ElementId*/, /*Delay before starting first fade - in milliseconds!*/);

Setting Up Fade Speeds, Display/Hide Times and Opacity Levels 

Find the following lines of code and change the values to achieve your desired result: 

JavaScript
//Value of opcity range 0 to 1
var MaxOpacity = 1.0;
var MinOpacity = 0.0;

//Time to take to fade the images - in milliseconds!
var FadeSpeed = 2000;
//Time to display the images for - in milliseconds!
var DisplayTime = 8000;
//Time to hide the images for - in milliseconds!
var HideTime = 0; 
  • MaxOpacity is the maximum opacity level you wish to fade to. This has to be within 0 and 1, with maximum two decimal places.
  • MinOpacity is the minimum opacity level you wish to fade to. This has to be within 0 and 1, with maximum two decimal places. It must also be less than MaxOpacity.
  • FadeSpeed is the length of time taken to fade out or in in milliseconds. I have it set to 2,000, a reasonably fast fade which looks good if you have a column of fading images. 
  • DisplayTime is the length of time between the image faded in being fully opaque and the next fade out starting (in milliseconds).
  • HideTime is the length of time between the image faded out being fully transparent and the next fade in starting (in milliseconds).  

Fade Image Method 

The new version contains only one FadeImage method that handles fading in and out images and looping the fades. You might ask why on earth anyone would need it when jQuery does fading for you but! jQuery does not do the looping for you nor will it allow fading to specific levels (not by default at least) and it wont handle thing like hide times, display times and initial delay times. The method looks like this: 

JavaScript
//Handles fading an image in and out
function FadeImage(Tag, Delay, NextOpacity)
{
    //If the NextOpacity is undefined, this is the first call and so do some setup
    if (NextOpacity === undefined)
    {
        //Load initial file indexes to prevent duplicates showing on first change
        var FileName = $("#" + Tag).attr("src");
        for (var i = 0; i < FileNames.length; i++)
        {
            if (FileNames[i].indexOf(FileName) > 0)
            {
                Files[Tag] = i;
                break;
            }
        }

        //Default opacity for elements is 1 so test if it's specifically set to 0
        if (parseFloat($("#" + Tag).css("opacity")) == 0)
        {
            NextOpacity = MaxOpacity;
        }
        else
        {
            NextOpacity = MinOpacity;
        }
    }
    //Is the next fade going to be a fade out
    var FadeOut = NextOpacity == MinOpacity;
    
    //If Delay were 0, it would be the same as null in the code Delay || ...
    if (Delay == 0)
        Delay = 1;

    //Get the image tag (by id so we need to add the hash symbol)
    $("#" + Tag)
        //Delay either the specified delay time (i.e. initial delay time) or hide/display time based on
    //fade in or out
        .delay(Delay || (FadeOut ? DisplayTime : HideTime))
        //Animate the image to fade to the next opacity
        //Uses the FadeSpeed and Linear easing. Function is the completed callback
        .animate({ opacity: NextOpacity }, FadeSpeed, "linear", function ()
    {
        //Runs when the fade is complete

        //If this is a fade out
        if (FadeOut)
            //Then now the image is hidden, load the next image
            $(this).attr("src", FileNames[Files[Tag] = GetNextFile(Tag)]);
        //And call FadeImage again to fade to do the next fade.
        //Since calls to delay/animate are (async) non-blocking calls,
        //this will return almost instantly. You don't end up with massive
        //call stacks as one may presume!
        FadeImage(Tag, null, FadeOut ? MaxOpacity : MinOpacity)
    });
} 

How does this work?

Well the first main bit is the initial set-up code contained within the first "if" block of the method. When the page first loads you will probably have set the images to have some initial URLs - its recommended so that the whole thing looks nice to the user as the page loads. So these images have been seen by the user. So to stop them immediately being re-shown (and to full-fill the spec of no duplicates) the code loads these initial values into the Files array. Then, since the images may be hidden initially we check to see if they need fading in or not, and set up accordingly.

The next bit is the determination of whether this is a fade out call or not, simply by checking if we are about to fade to MinOpacity or not and the "if" block for checking Delay.  In JavaScript we can use x || y to say "if x is something, use x, otherwise use y". Unfortunately, this operator counts "0" as being nothing and so would later use y not our Delay object, which is why, if Delay is zero, we set it to one. Delay is in milliseconds so this 1 millisecond extra delay will not be seen. 

Next we use jQuery to get our element. Since jQuery uses the CSS specification for identifying elements, we add a hash to the start of the id. Then we call the delay method. This is non-blocking and simply queues a delay on the effects queue for the current object, this is why the recursion of the FadeImage method works without eval or setTimeout. If methods delay and animate were blocking, we would end up with a large call stack which would eventually result in an error. The delay time that we pass into the delay method is determined by the following:

If Delay is set, we want to use that. 
If Delay is not set and this is a fade out, we should delay for the DisplayTime before fading out.
Otherwise, this is a fade in and we should delay for the HideTime before fading in. 

The code for all that? A nice and simple one line:  Delay || (FadeOut ? DisplayTime : HideTime) 

Finally we make a call to animate, passing in our NextOpacity level as the CSS property to be animated, FadeSpeed, a "linear" gradient function should be used and finally a callback function to allow us to call the next fade. The callback function then checks to see if a new image needs selecting then calls the next fade with no delay time and the correct next opacity depending on whether the next should be a fade in or out.

Get Next File Method

This simply returns the index in the FileNames array of the next image to show.  It handles making sure there are (almost) never duplicates showing and never two of the same image in a row. It should be noted that this method could go on never returning a file name for an infinite length of time, but the probability of this happening in practice is so low that it is not worth worrying about. 

Points of Interest 

Some points of interest from the initial version were: the setTimeout function is not accurate; the floats get progressively worse floating point errors rather rapdily, and IE and Opera JavaScript runs significantly slower than that of the 3 other major browsers. 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)