HI there,
I wonder if anybody can give me a hand with this.
I am writing a script which will allow me to swap some images (using also jquery to give the fading effect) but things are not quite working the way they should. I am really new to javascript and to jquery, and even if I am reading tutorial and try to practice my code is still a bit dodgy.
Now, this is what I came up with:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1">

<title>Photography Home</title>

<link rel="stylesheet" type="text/css" href="containers.css">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript">
<!--

var myImages=new Array("test1.jpg", "test2.jpg", "test3.jpg");
var temp;

function swapImages()
{
var randomNumber=Math.floor(Math.random()*myImages.length);

if(temp==randomNumber) //so that the picture inserted is always different

{
return swapImages()
}

temp=randomNumber;

imageOut(randomNumber);

  }



function imageOut(number)
{


$("#picture").fadeOut(2000);
imageIn(number);



}


function imageIn(imageGenerated)
{

document.getElementById('picture').src = myImages[imageGenerated];



  $("#picture").fadeIn(2000);

setTimeout("swapImages()",2000);
}



//-->
</script>

</head>

<body id="page_body" onload="swapImages()">

<div class="wrapper"> <!-- MAIN CONTAINER -->
<p>
<img src="test1.jpg" id="picture" alt=" ">
</p>
</div>




</body>

</html>

The rest of the code with images and css is on a test site here: http://antobbo.webspace.virginmedia.com/javascript_tests/2011_05_26/test.htm
What I have done in the code is to create 3 functions: swapImages(), imageOut(), imageIn() and pass a parameter to the functions which I will eventually use to swap the images.
Now, the problem is that the transition from one image to another, as you can see in from the above link, is not that smooth, and I don't quite understand why. I know that the reason will probably be obvious to you but I wonder if you could possibly take a little bit of time to explain it to me too : - )
thanks a lot

Recommended Answers

All 9 Replies

Not smooth ? What does it mean ? It is working nicely in my PC.

Hi Zero13,
well the transition is smooth only for the first 2 images, and it seems to go on a 2-by-2 basis, as in when you load the page the first picture fades out and the second one fades in fine, but the third suddenly appears on the screen, then fades out nicely and the third fades in nicely...the again the 4th appears suddenly...if you let it run you will see : - )
Basically I would like all the pictures to fade in and out

Violet,

The reason the transitions are not smooth is due to the size of the images. At 300k to 400k the fadeout/fadein effects give browser and graphics card a lot of work to do. Zero 13 is probably driving something ritzy, at least ritzier than this 9 year old machine.

Try with images of no more than about 70k and you should find the transitions are a lot smoother.

Also, your JavaScript can be written in a more jQuery sort of way, like this:

$(document).ready(function() {
	var myImages = [ "test1.jpg", "test2.jpg", "test3.jpg" ];
	myImages.current = 0;
	function swapImages(){
		var randomNumber;
		while( myImages.current === (randomNumber = Math.floor(Math.random()*myImages.length)) ){ ; }//loop to reject same consecutive image
		myImages.current = randomNumber;
		//now perform the fadeout, fadein and schedule next image in cascade.
		$("#picture").fadeOut(2000, function(){
			$(this).attr('src',myImages[randomNumber]).fadeIn(2000, function(){
				setTimeout(swapImages, 2000);
			});
		});
	}
	swapImages();
});

This will look a bit weird but tests out ok, and works well with the thumbnail versions of your images.

Airshow

Airshow,
thanks for that and the code - which is a bit advanced for me but I will study it carefully.
ABout the issue of images transition, sorry to labour the point, but I am not too sure it depends solely on the type of graphic card or the size of the picture. I actually think that there is some error in my code. The reason is that I have a fairly good graphic card but the image transition is not smooth at all. Let me show you this example which should hopefully clarify the matter, or maybe confuse it. If we compare my script here http://antobbo.webspace.virginmedia.com/javascript_tests/2011_05_26/test.htm
with another version (somebody else did this script for me and I really don't want to merely copy it but I want to some how do it myself) http://antobbo.webspace.virginmedia.com/photography/home.htm
you surely will see the difference. The picture size is the same but the transition effect is different.
The second script is in essence this:

...
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>

<script type="text/javascript">

  var preloads=[];


function preload(){


for(var i=0;i<arguments.length;i++) {
  preloads[preloads.length]=new Image();
  preloads[preloads.length-1].src=arguments[i];

  }

 }

preload('images/test1.jpg','images/test2.jpg','images/test3.jpg');

  var delay=4000; //call function "displayImages()" 4 every seconds
  var temp;
  var test=true;
  var randomNumber;

function displayImages() {

  test==true?(test=false,out()):(test=true,ink());

 }

function out(){
  setTimeout(function(){displayImages()},delay);
  $("#pic").fadeOut(delay)
 }

function ink(){
  randomNumber=Math.floor(Math.random()*preloads.length);
if(randomNumber==temp) {
  return ink();
 }
  temp=randomNumber;

  document.getElementById('pic').src=preloads[randomNumber].src;
  setTimeout(function(){displayImages()},delay);
  $("#pic").fadeIn(delay)
 }
  window.addEventListener?
  window.addEventListener('load',displayImages,false):
  window.attachEvent('onload',displayImages);
</script>

</head>
<body id="page_body">

<div class="wrapper"> <!-- MAIN CONTAINER -->

<div class="wrap_content"> <!-- BOX FOR CONTENT-->
<div class="banner"> <!--BOX FOR BANNER -->
</div> <!--END OF BOX FOR BANNER -->

<h1 id="foo">AB Photography</h1>

<div class="navigation_menu"> <!-- TOP NAVIGATION BOX-->

<ul>
 <li class="button1"><a href="home.htm">Home</a></li>
 <li class="button2"><a href="gallery.htm">Gallery</a></li>
 <li class="button3"><a href="#">Test3</a></li>
 <li class="button4"><a href="#">Test4</a></li>
</ul>

</div><!-- END OF TOP NAVIGATION BOX-->

<div class="categories"><!-- CATEGORY BOXES IN GALLERY PAGE -->


<div class="picture_box_home"><!-- PICTURE BOX-->



 <div class="in_pic"><!-- SECOND BOX  -->

 <div class="in_pic1"><!-- THIRD BOX  -->

 <img id="pic" src="images/test1.jpg" alt="" class="slideshow">

 </div><!-- END THIRD BOX  -->
...

Hope that makes sense
thanks

Violet,

OK, I've got a fastish netbook available to me this evening in addition to my old desktop machine. Here's what I get ...

Old Desktop: Same as you. v1 is jerky, v2 is smooth.
Netbook: Both versions are very smooth but the two versions swap the image at a different point in the cycle.

I can't fully explain this however, I can say that the main difference in the code lies in v1's imageOut() being not the same as v2's out() .

It's possible that your imageOut doesn't work quite as you might expect.

function imageOut(number)
{
  $("#picture").fadeOut(2000);
  imageIn(number);
}

Here, the fadeout is initiated, but no more than that, then execution drops straight through to the next line, imageIn(number) .

Consequently, imageIn is initiated well before imageout 's fadeout has completed.

The v2 code attempts to overcome this with a setTimeout to give a delay coinciding with the fadeout's duration. This will sort of work but could potentially suffer from synchronisation problems if the animation is left to run for some time, especially in there are other processor intensive programs or browser pages running on the user's computer. In this case v1's lack of smoothness could become manifest.

A solution is for each cycle to consist of a cascade of function calls with just one setTimeout to stimulate the next cycle. This is exactly what is going on in the code I posted above.

Airshow

Airshow,
thanks for the explanation, it is clearer now. I used your code and it works a treat http://www.antobbo.webspace.virginmedia.com/javascript_tests/2011_05_26/test.htm
although there are few things that I don't understand. I googled it but I couldn't find much: when you say

myImages.current = 0;

and

myImages.current = randomNumber;

what's that "current", is it an attribute standing for "current image"? I couldn't find any reference anywhere.
Also when you say

var randomNumber;
		while( myImages.current === (randomNumber = Math.floor(Math.random()*myImages.length)) ){ ; }

the loop basically says "while a new image is equal to the current do nothing"...but how do you come out of it?
thanks

when you say myImages.current = 0; and myImages.current = randomNumber; what's that "current", is it an attribute standing for "current image"? I couldn't find any reference anywhere.

Yes, myImages.current stands for "current image". Javascript arrays can have both indexed (numbered) members and associative (named) members. By using an associative member of myImages, we "pollute the namespace" slightly less than by using a completely independent member name. In a small script like this, it's not really an issue but in large, complex scripts, minimising the number of members in each namespace can be very necessary. Thus we reduce the possibility of "name collision" (the inadvertent reuse of a member's name).

Also when you say

var randomNumber;
		while( myImages.current === (randomNumber = Math.floor(Math.random()*myImages.length)) ){ ; }

the loop basically says "while a new image is equal to the current do nothing"...but how do you come out of it?
thanks

This a shorhand way to make an assignment and perform a while loop test all in one line. Some programmers consider this bad coding practice, mainly (I think) because the code can be difficult to read. Here, I decided to use this "assignment in loop test" pattern because it saves several lines of code. I also decided that iteration was better than recursion, as per the original code.

In my while loop, if the assignment generates a randomNumber equal to myImages.current , then execution flows to another iteration of the loop (it tries again).

The exit condition arises as soon as a randomNumber is generated, which is not equal to myImages.current - ie. exactly what we want - a different valid integer.

My code could be improved to add some safety. As it stands, for an myImages array with zero or one member, the code will give an error.

Airshow

ah ok, thanks Airshow, that's much better now. What was confusing me was actually this

{ ; }

but that's just the empty body of the while loop! Now I understand. thanks for the code and the explanation, much appreciated!

Yes, exactly so.

It's good practice to include a semicolon in an empty loop body as a marker to show that it is deliberately empty and so it doesn't look like the shorthand version of new Object(), {} .

Airshow

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.