http://www.siteexperts.com/tips/styles/ts23/page2.asp

This page includes a cursor trail. The trail consists of 5 CSS layers each consisting of an image that makes up the trail. I'll call this combination of an image in its own layer a 'sprite'. As shown here:
	
<DIV id="trailSprite1" style="position: absolute; height:28px; width:36px;">
  <img src="trailgif1.gif" height=28 width=36 border=0>
</DIV>

References to these sprites ID are stored in an array as a string. The ID's are named trailsprite1, trailsprite2, trailsprite3, etc. This array is treated like a kind of 'queue'. When the mouse moves, the last sprite ID in the array is positioned closest to the mouse's current position (there's a slight offset so the trail doesn't cover up anything clickable). The array is then shifted by 1 element so this last reference becomes the first. This process continues so the queue is 'looped' around on its self and therefore there's alway's a sprite available for the trail.

Next we will show you step by step how we created this effect.

Page 1:Cursor Trails
Page 2:Trails Demonstration
Page 3:Creating Cursor Trails
Page 4:Improving the Trail

SiteExperts.com Logo Home | Community | Developer's Paradise | Jobs
User Groups | Site Tools | Site Information | Search
www.SiteExperts.com

Inside Technique : Cursor Trails : Creating Cursor Trails

Forgetting about the fade for the moment the code to achieve a simple trail runs like this:

  1. Initialize variables, events and fill the queue with the sprite names, which is done with the init function.
    function init() {
    	// fill the queue array with the layer names	
    	for(x=0; x < NUM_OF_TRAIL_PARTS; x++)
    		// which are numbered dot1, dot2 .. in sequence
    		queue[x] = "trailSprite" + (x+1) ;
    	// Tell the browser what events we want to capture (Netscape)
    	if (isNS) { document.captureEvents(Event.MOUSEMOVE); } 
    	document.onmousemove = processMouse;  // And where there to go.
    }	
    
  2. When the mouse moves, get the last sprite ID reference from the queue array and position this sprite closest to the mouse. This is accomplished by the processMouse function:
    		
    function processMouse(e) {
    			
    	//	Get the last sprite reference of the 'queue'.
    		currentObj = shuffleQueue();
    	
    	//	Depending on the browser, position this trail part near the mouse 
    	//	co-ordinates offsetting by 10 pixels so it dosn't get in the way of 
    	//	links etc.
    	if (isNS) {
    		eval("document." + currentObj + ".left = e.pageX - 10 ;");
    		eval("document." + currentObj + ".top = e.pageY + 10;");
    	} else {
    		eval("document.all." + currentObj + ".style.pixelLeft = event.clientX + document.body.scrollLeft - 10 ;");
    		eval("document.all." + currentObj + ".style.pixelTop = event.clientY + document.body.scrollTop - 10;");
    	}
    }
    
  3. Move the rest of the queue's references back an element and put the last element at the front. The 'shuffle' function does this:
    		
    function shuffleQueue() {
    	lastItemPos = queue.length - 1;	 // get the position of the last item of the que
    	lastItem = queue[lastItemPos];	 // get the actual item
    	for (i = lastItemPos; i>0; i--)  // Now move the rest of the que back one 
    		queue[i] = queue[i-1];
    	queue[0] = lastItem;		 // Replace the last item at the front
    	return 	queue[0];		 // and then return it
    }
    
  4. repeat step 2 when the mouse moves.

This this is a basic trail, but it kind of gets in the way of whats on the page. Next we improve the trail to constantly fade. The fade consists of a five frame animation of a trail part getting gradually smaller before dissapearing completely. The animation for a sprite is started when it's moved closest to the mouse. This gives the effect of the trail graduating away as the mouse is moved and disappearing completely when mouse movement is stopped.

SiteExperts.com Logo Home | Community | Developer's Paradise | Jobs
User Groups | Site Tools | Site Information | Search
www.SiteExperts.com

Inside Technique : Cursor Trails : Improving the Trail

First, five GIF's needed to be created for the animation. All are the same dimensions but with an increasing amount of transparent area and the dot (in this case) gets smaller. These sprites will need to be preloaded. The filenames of the sprites are trailgif1.gif, trailgif2.gif, trailgif3.gif, etc. A name attribute also needs to be added to each sprite img tag so the scripting can reference it.

Compared to the basic trail, the scripting becomes a more complicated when it comes to the adding the fade. The queue now has to track not just a string reference to each sprites ID, but also its current frame and, if its in an active state, look after the animation.

This is ideal scenario for using a basic Javascript Object. Rather than filling the queue array with just strings that reference layers, we'll fill the array with objects that reference not only the sprites ID, but also a reference to the sprites image and the sprites current frame of fade animation. This simple object will also have one method which performs and looks after the animation process. Here is the trail object:

function trailSpriteObj(anID) {
	this.trailSpriteID = "trailSprite" + anID; //as before 
	this.imgRef = "trailSprite" + anID + "img"; //reference to the sprites image name
	this.currentFrame = 1; //the varible for looking after the frame
	this.animateTrailSprite = animateTrailSprite; //declare the objects method cycle
}
	
function animateTrailSprite() {
	if (this.currentFrame <6 ) { //if there are animation frames left, the change sprites the current frame
		if (isNS) { 
			eval("document." + this.trailSpriteID +".document['"+ this.imgRef + "'].src  =  trailSpriteFrame" + this.currentFrame + ".src");
		} else {
			eval("document['" + this.imgRef + "'].src  =  trailSpriteFrame" + this.currentFrame + ".src");
		}
		this.currentFrame ++; //and increase the objects current frame 
	} else { //the current frame has reached its limit so hide the sprite
		eval(layerRef + '.' + this.trailSpriteID +  styleRef + '.visibility = "hidden"');
	}	
}

The queue array is now filled with instances of this object:

for(x=0; x< NUM_OF_TRAIL_PARTS; x++)
	queue[x] = new trailSpriteObj(x+1) ;

The Object is constructed with just 1 parameter, a number related to the sprites ID in the HTML.

Another function is also introduced which fires off each objects 'animateTrailSprite' function. The processAnim fuction shown below simply calls each objects cycle function. 'processAnim' is added to a 'setinterval' function so it is called regularly.

function processAnim() {
	for(x=0; x<5; x++)
		queue[x].animateTrailSprite();
}

Now if this code is run, the mouse trail will just simply disappear and not reappear. To fix this, a couple of extra lines need to be added to the queue shufferling function. Now the sprite its getting from the back of the queue and moving closest to the mouse has its animation reset, by making it visible and setting its curent frame to 1 . The lines are:

	
queue[0].currentFrame = 1; //reset the objects frame number
eval(layerRef + '.' + queue[0].trailSpriteID +  styleRef + '.visibility = "visible"'); //make the sprite visible again

And thats it - now the trail now quite happily fades away.

Now the final thing to do is to make it work with older, less dynamic, browsers. Because in the script tag we've told the browser its version 1.2 Javascript older browsers will ignore it. The simplest way to avoid the images between the div tag appearing in older browsers is to put the tags at the very bottom of your page and replace the dot images with a blank transparent gif, with the same dimensions as a trail part. Using a <span> tag rather than a <div> will also stop the page from trailing off to long (A div causes a line break, whilst a span doesn't).

About the Author

Matthew Allum is a 23 year old programmer from the UK. He works on the websites for a large consumer magazine publisher located at www.erack.com. Apart from coding in various Internet technologies, he also enjoys cruising in his Karmann Ghia, collecting obscure records and just hanging out. His home page is located at http://hopskotch.eimages.co.uk.

Discuss and Rate this Article