Fading In With Javascript

Some months ago, through a long-forgotten source, I came across this technique for fading in images without using flash and I’ve been looking for an excuse to play around with such techniques. Today, work on a new page for Calvin gave me such an excuse.

I wanted to use the technique within a javascript image gallery. I needed to be able to advance through a set of images and wanted to fade each in in turn. Since the images were named numerically, all it appeared to involve was a couple of javascript functions to increment or decrement a counter and update the photo accordingly. Because I’d be using the same image tag for all the images, I also tweaked the original’s functions to use a predefined object rather than making use of the DOM each time.

It all worked splendidly on my local server, but uploading to a test server I realised that I’d need to preload the images if I wanted to avoid flickering. I added in calls to check whether the next image had been previously loaded, and if not preload it into an array, and the flickering disappeared.

The resulting code is:


	/* counter keeps track of which image we're displaying */
	var counter;

	/* display will be the pointer to the image object we're
	 * working with
	 */
	var display;

	/* totalimages is the number of images we're displaying, so we can reset
	 * counter if necessary
	 */
	var totalimages = 9;

	/*
	 * pics will hold our pre-loaded images
	 */
	var pics = new Array();

	/* This function is called by the onload attribute of the
	 * body tag
	 */
	function initPage()
	{
		container = document.getElementById('display');
		display = document.getElementById('display_image');
		counter = 1;
		pics[1] = new Image();
		pics[1].src = 'slideshow/1.jpg';
		pics[2] = new Image();
		pics[2].src = 'slideshow/2.jpg';
		pics[totalimages] = new Image();
		pics[totalimages].src = 'slideshow/'+totalimages+'.jpg';
	}

	function advance()
	{
		if (counter == totalimages) {
			counter = 1;
			nextcounter = 2;
		} else if (counter == totalimages - 1) {
			counter++
			nexcounter = 1;
		} else {
			counter++;
			nextcounter = counter + 1;
		}
		setOpacity(0);
		display.src = 'slideshow/'+counter+'.jpg';
		if (! pics[nextcounter]) {
			pics[nextcounter] = new Image();
			pics[nextcounter].src = 'slideshow/'+nextcounter+'.jpg';
		}
		fadeIn(0);
	}

	function retreat()
	{
		if (counter == 1) {
			counter = totalimages;
			nextcounter = counter - 1;
		} else if (counter == 2) {
			counter--;
			nextcounter = totalimages;
		} else {
			counter--;
			nextcounter = counter - 1;
		}
		setOpacity(0);
		display.src = 'slideshow/'+counter+'.jpg';
		if (! pics[nextcounter]) {
			pics[nextcounter] = new Image();
			pics[nextcounter].src = 'slideshow/'+nextcounter+'.jpg';
		}
		fadeIn(0);
	}

	/* Altered from the original to use the global 'display'
	 * object
	 */
	function setOpacity(opacity)
	{
		opacity = (opacity == 100)?99.999:opacity;

		// IE/Win
		display.style.filter = "alpha(opacity:"+opacity+")";

		// Safari<1.2, Konqueror
		display.style.KHTMLOpacity = opacity/100;

		// Older Mozilla and Firefox
		display.style.MozOpacity = opacity/100;

		// Safari 1.2, newer Firefox and Mozilla, CSS3
		display.style.opacity = opacity/100;
	}

	/* Altered from the original to use the global 'display'
	 * object
	 */
	function fadeIn(opacity)
	{
		if (opacity < = 100)
		{
			setOpacity(opacity);
			opacity += 10;
			window.setTimeout("fadeIn("+opacity+")", 100);
		}
	}

Since it will eventually load all the images into an array, this may not be a good technique to use with large galleries. But for a small one, such as that I was working with there isn’t much to worry about.

UPDATE: I’ve refined this method further and written about it here.

Tags: , ,

2 comments

  1. Looks great – but the title suggests you were going to do it *without* JavaScript!

    (Now _that_ would be impressive)

  2. Oops! That’s quite a typo. Thanks for pointing it out, I’ve changed the title.