A Javascript + CSS replacement for Flash photo fading slideshow. Inspired by Richard Rutter's image fade demonstration.
Example
The XHTML
Just like Richard's setup: an image in a div
<div id="photodiv"><img id="photoimg" src="bb3d0d6134.jpg" /></div>
The XHTML contains the image that will be both the first and the last image shown. The other image source values are put into the javascript routine.
The Setup
The customization section lets you set up how many photos in the deck and how many times you want to run through the deck.
var gblPhotoShufflerDivId = "photodiv";var gblPhotoShufflerImgId = "photoimg"; var gblImg = new Array( "78ebdaf8bc.jpg", "3523869ba4.jpg", "fabcf2f7ce.jpg" );var gblPauseSeconds = 7.25;var gblFadeSeconds = .85;var gblRotations = 1;
Specify unique IDs for your image and div. Load up the array with source paths to images to place into the rotation.
Pause seconds and fade seconds are pretty self-explanatory. I like fades to be between .75 and 2 seconds. Regardless of how long you choose to fade the image, I compute a fade call at 30fps, so even excruciatingly long fades have fairly smooth transitions.
Rotations allows you to move through the deck multiple times. It accepts a value of zero, meaning show each image in the deck then stop.
The Fade
You can hook the photoShufflerLaunch routine into your onload event by whatever means you prefer. It will load the first image from the array into the div background and pause the specified number of seconds.
When the timer pops, the image will fade to reveal the div background.
function photoShufflerFade(){ var theimg = document.getElementById(gblPhotoShufflerImgId); // determine delta based on number of fade seconds // the slower the fade the more increments needed var fadeDelta = 100 / (30 * gblFadeSeconds); // fade top out to reveal bottom image if (gblOpacity < 2*fadeDelta ) { gblOpacity = 100; // stop the rotation if we're done if (gblImageRotations < 1) return; photoShufflerShuffle(); // pause before next fade setTimeout("photoShufflerFade()",gblPauseSeconds*1000); } else { gblOpacity -= fadeDelta; setOpacity(theimg,gblOpacity); setTimeout("photoShufflerFade()",30); // 1/30th of a second }}
The Shuffle
Then I shuffle the deck.
Once the div background is fully revealed, I pop the background image source value into the (transparent) image source attribute and set the opacity of the image to 100 percent. The image is fully opaque and completely hides the div background, which at this point, is the same photo.
function photoShufflerShuffle(){ var thediv = document.getElementById(gblPhotoShufflerDivId); var theimg = document.getElementById(gblPhotoShufflerImgId); // copy div background-image to img.src theimg.src = gblImg[gblOnDeck]; // set img opacity to 100 setOpacity(theimg,100); // shuffle the deck gblOnDeck = ++gblOnDeck % gblDeckSize; // decrement rotation counter if (--gblImageRotations < 1) { // insert start/final image if we're done gblImg[gblOnDeck] = gblStartImg; } // slide next image underneath thediv.style.backgroundImage='url(' + gblImg[gblOnDeck] + ')';}
I set the background image to the next photo in line, and pause the specified number of seconds.
When the timer pops, the image will fade to reveal the div background. I work through the rotation the specified number of times, then show the first photo again and stop.
Caching
As my Stanford professors were wont to say, ensuring that a photo is loaded before fading to it "...is left as an exercise for the student."
Since the photos are loaded as div backgrounds for the duration of the pause, they have a few seconds to load. I haven't seen any broken images yet, but I have fairly decent bandwith capabilities at home.
Accessibility, Compatibility
- Javascript off - first image appears without animation.
- Javascript and CSS off - first image appears without animation.
- CSS off - div extends out and the background repeats
- Images off - Alt text is displayed
- application/xhtml+xml - works fine, does not use document.write()
In practice, I put the CSS and JavaScript into their own files. For this demo page, I've included everything together as a unit for improved portability.