Fade Between Images with jQuery

jQuery’s fadeIn and fadeOut make it easy to fade images into a solid color but not into another image. We fixed that. With this function, you can fade directly from one image to another with jQuery, and even make a looping slideshow.

You can’t fade from one image directly into another, but you can fade out an image that’s sitting on top of another image. I got the idea for this from a post that showed a bunch of images stacked on top of each other with Z-indexes. That seemed problematic, so I thought of another solution: I could set the background-image of the container div with CSS, then fade out the image on top of it. To string multiple photos together, you just alternate between fading in an <img> with the new image and fading out to reveal the new image in the background div. It sounds more complicated than it is.

All you have to do is copy and paste the fade_images function, then provide a list of your images and (optionally) a few arguments to customize it. Here’s an example:

$images = array(
	'/images/inkplant/code/colorado1.jpg',
	'/images/inkplant/code/colorado2.jpg',
	'/images/inkplant/code/colorado3.jpg',
	'/images/inkplant/code/colorado4.jpg',
);
echo fade_images($images,'colorado_slideshow','colorado_photo');

And here’s the result, with a few photographs I snapped near Tolland, Colorado, as an example:

This is the HTML and JavaScript generated by fade_images that’s displaying that:

<!-- Error! Could not get image width: /images/inkplant/code/colorado1.jpg -->

Last but not least, here’s the PHP function itself:

<?php

function fade_images($images=array(), $div_id='fade', $img_id='fade_img', $repeat=true, $delay=1000, $speed=500, $return_array=false, $minify=false) {

	if ($minify) {
		$lb = ''; $tab = '';
	} else {
		$lb = "\n"; $tab = "\t";
	}

	//note: the images should all be the same size
	$img_size = @getimagesize(reset($images));
	if (empty($img_size['0'])) { echo '<!-- Error! Could not get image width: '.reset($images).' -->'; return false; }
	$img_width = $img_size['0'];

	$html = '<div id="'.$div_id.'" style="background-repeat:no-repeat;background-size:100% auto;width:'.$img_width.'px;max-width:100%;">'.$lb;
	  $html .= $tab.'<img id="'.$img_id.'" src="'.reset($images).'" alt="image" style="max-width:100%;">'.$lb;
	$html .= '</div>'.$lb.$lb;

	$js_start = 'window.setTimeout(update_img_to_2,'.$delay.');';

	$i = 0;
	$js_functions = '';
	foreach ($images as $image) {
		$html .= '<img src="'.$image.'" style="width:1px;height:1px;visibility:hidden;">'.$lb; //pre-load image
		$i++;
		if (($i > 1) || ($repeat)) {
			$js_functions .= 'function update_img_to_'.$i.'() {'.$lb;

				//determine next function
				if ($i < count($images)) {
					$next = 'update_img_to_'.($i+1).'();';
				} else {
					if ($repeat) { $next = 'update_img_to_1();'; }
					else { $next = ''; }
				}

				if (($i/2) == round($i/2)) { //even numbered images fade out
					$js_functions .= $tab.'$(\'#'.$div_id.'\').css(\'background-image\',\'url('.$image.')\');'.$lb; //update the background to the new image
					$js_functions .= $tab.'var ch = $(\'#'.$div_id.'\').height();'.$lb; //get current height of div and then set it so that div doesn't shrink when img goes away
					$js_functions .= $tab.'$(\'#'.$div_id.'\').height(ch);'.$lb;
					$js_functions .= $tab.'$(\'#'.$img_id.'\').delay('.$delay.').fadeOut('.$speed.',function(){'.$next.'});'.$lb;
				} else { //odd numbered images fade in
					$js_functions .= $tab.'$(\'#'.$img_id.'\').attr(\'src\',\''.$image.'\');'.$lb; //update the hidden img to the new image
					$js_functions .= $tab.'$(\'#'.$img_id.'\').delay('.$delay.').fadeIn('.$speed.',function(){'.$next.'});'.$lb;
				}
			$js_functions .= '}'.$lb.$lb;
		}
	}

	//note: we use window.onload to make sure both jQuery and the images have loaded before we begin
	$js = 'window.onload = function() {'.$lb;
		$js .= $tab.$js_start.$lb;
	$js .= '};'.$lb.$lb;
	$js .= $js_functions;

	if ($return_array) { return array('html'=>$html,'js'=>$js,'js_start'=>$js_start,'js_functions'=>$js_functions); }
	else { return $html.$lb.$lb.'<script>'.$lb.$js.'</script>'; }
}

?>

One caveat: The repeat functionality is clunky with an odd number of photos. So, either stick to an even number, or come up with a clever workaround. If the latter, let us know how in the comments below.


Comments

Loading…

This post was first published on July 22nd, 2018 and last updated on July 25th, 2018 by Robert James Reese in the following categories: JavaScript, jQuery, and PHP Before using any of the code or other content in this post, you must read and agree to our terms of use.