Archive for April, 2009

Circular Image Slide with jQuery

April 25, 2009 32 comments

A friend of mine asked me to write a little script for him the other day that would do the following :

1. Slide a list of images from right to left across the screen.
2. When an image moves out of view on the left, it should get appended to the end of the list thus creating the illusion of a never ending or circular procession of images across the screen.
3. Display a “loader” image while the photographs are downloading.
4. You can view a demo of the end result here.

My first impression was that there’s almost certainly a jQuery plugin capable of doing this. Well if there is, I haven’t found it yet. While there are a myriad of “Slide” plugins available, and some come quite close, none could fulfill these requirements.

So I had to go and write my own little script. I haven’t converted the code to plugin form just yet as I need to look a few things up.

If you’d like to just jump straight in, here’s a zipped version of the demo.

First, the HTML:

<div id="slider">
<div id="imageloader">
			<img src="images/ajax-loader.gif" /></div>
<img src="images/sample1.jpg" />
		<img src="images/sample2.jpg" />
		<img src="images/sample3.jpg" />
		<img src="images/sample4.jpg" />
		<img src="images/sample5.jpg" /></div>

Nothing out of the ordinary here, just a div with a bunch of image tags. The only thing to note is the div’s “id”. The real magic happens in the JS and CSS. The pre-loader image is located inside a nested div with an id of “imageloader”. By default, our loader will be visible while our photographs are hidden.

That brings us to the CSS:

#slider {position: relative; overflow: hidden; height:155px;}
#slider img {position:absolute;	margin:0; display:none;}
#imageloader {position:relative; display:block; width: 100%; margin: 0px auto; text-align: center;}
#imageloader img { position:relative; top:70px; z-index:100; width:128px; height:15px; display:inline;}

Firstly, due to the nature of the script we have to make use of relative and absolute positioning. With that in mind, we first set our container div to relative positioning. This allows us to assign an absolute position to each child image, this is critical to the functioning of this script.

Next we set the overflow style to “hidden” – this makes sure that we don’t get ugly scroll-bars when images are moving outside of the containing div’s bounds.

We also need to set a fixed height for the container div. Failing to do so will result in the images not being displayed at all (due to the absolute positioning and overflow setting).

For the nested images, we want to set their initial display attribute to “none”. This is so they don’t display until our DOM is ready and all the images are loaded. We also need to set their positions to absolute.

For the pre-loader we just set some styles to make sure it get’s displayed in the correct position : in this case 70px from the top and horizontally in the middle of the container div. We also make sure to set the display attribute to “inline”, thus making sure the pre-loader img is shown while all other img’s are hidden.

Now for the Javascript/jQuery:

var speed = 50;
var pic, numImgs, arrLeft, i, totalWidth, n, myInterval;

pic = $(“#slider”).children(“img”);
numImgs = pic.length;
arrLeft = new Array(numImgs);

for (i=0;i

  • We use $(window).load() instead of the standard $(function(){}) or $(document).ready() methods due to a timing glitch in Safari. Safari reports the DOM as finished loading even while images are still downloading – not ideal if we want our pre-loader to work correctly.
  • When the DOM has finished loading, and the images have finished downloading we execute our code.
  • First we read all our images into an array of jQuery objects. We make sure the pre-loader isn’t included in this array by using $(“#slider”).children(“img”) instead of $(“#slider img”).
  • Next we loop through each image in our array and calculate a totalWidth. We need this value so that we know where to append each image when needed. Within this loop, we also set the correct absolute position for each image so that they all line up next to each other. Otherwise they’d all just sit on top of each other.
  • Once our loop is complete and we have all the initial positions setup, we create a standard javascript interval. Using this interval we can call a function every x milliseconds. We use the “speed” variable to make this configurable.
  • Now that everything’s set up, we hide our pre-loader, unhide our images and wait for the interval to fire.
  • The “flexiScroll()” function simply moves each image to the left by 1 pixel, recalculates the totalWidth and if necessary, moves the left-most image to the end of the list. Since the end of the list is currently outside of the viewable area, this gives the illusion that the list never ends.

    And that’s all there is to it.

    There of course must be a more efficient way of doing this, so if you would like to contribute, please leave a comment or contact me.