Tuesday, May 11, 2010

Single Image Fade In - Fade Out

If  anyone has visited the Boston Globe website and seen their "The Big Picture" page you would be awe struck by the amazing photographs.  I always go there to see the amazing photos around the world and just makes me feel humble and pathetic about my photography skills.  I guess it gives me something to strive for.  For now I know that my photography knowledge might not be as skillful but at least I know how to extract code that I believe is quite effectively used.

If you visit the Earth Hour 2010 page from Boston Globe they have a great way of transitioning images from dark into light.  Great setup and I thought it was skillfully executed.  From a developer point of view I wanted to see the JavaScript involved in fading one image into the next that seems to work across IE and Firefox without any glitches so I started to dissect the code and here is what I found.

The main JavaScript use for fading is very small and simple:
<script>

var isFading = 0;

function setOpacity(obj, opacity){opacity = (opacity == 100)?99.999:opacity;obj.style.filter = "alpha(opacity:"+opacity+")";obj.style.KHTMLOpacity = opacity/100;obj.style.MozOpacity = opacity/100;obj.style.opacity = opacity/100;};

function fadIn(objId,opacity,sc){if(((sc==1)&&(isFading == 0))||(sc==0)){isFading = 1;if (document.getElementById) {obj = document.getElementById(objId);if (opacity >= 0){setOpacity(obj, opacity);opacity -= 10;window.setTimeout("fadIn('"+objId+"',"+opacity+",0)", 100)}else{obj.style.display="none";isFading = 0}}}};

function fadOut(objId,opacity,sc){if(((sc==1)&&(isFading == 0))||(sc==0)){isFading = 1;if (document.getElementById){obj = document.getElementById(objId);obj.style.display="";if (opacity <= 100){setOpacity(obj, opacity);opacity += 10;window.setTimeout("fadOut('"+objId+"',"+opacity+",0)", 100)}else{isFading = 0}}}}

</script>

I honestly don't care too much about understanding the code other than just knowing that it works. The next part was just calling the fadIn or fadOut functions.
<a href="#" onclick="this.blur();fadOut('imgA',0,1);return false">
<img src="img_off.jpg" style="height:658px;width:990px;border:0px;" /></a>
<br/>
<div style="margin-top:-658px;height:658px;width:990px;position:relative;" id="imgA">
<!-- the initial picture to display -->
<a target="_new" href="img_off.jpg" onclick="this.blur();fadIn('imgA',100,1);return false">
<img src="img_on.jpg" style="height:658px;width:990px;border:0px;" /></a>
</div>

Well after looking at how the fadIn and FadOut functions are called I saw what the trick or illusion is.  If you look at the div style attribute you will see the -658px value and that is where the trick lies.  Initially I thought the JS script was going to retrieve the next image and fade it in but this is even better, there won't be any delay of waiting for an image to download it would just work.

Here is how it works just to make it clear, HTML is rendered sequentially and the first image that is rendered is img_off.jpg and img_on is rendered right underneath.  Since the div has the top-margin style attribute of -658px (the height of the image)  for img_on.jpg it will overlay img_off.jpg.  In-essences they are stacked on top of one another.  The JavaScript is only changing the opacity to fade out one image and revealing the other.  I hope all that made sense if you even wanted to understand what's going on.  For the lazy people like me.   Here is the complete code that you can simply use to test it out.
<div>

<a href="#" onclick="this.blur();fadOut('imgA',0,1);return false">
<img src="img_off.jpg" style="height:658px;width:990px;border:0px;" /></a>
<br/>

<div style="margin-top:-658px;height:658px;width:990px;position:relative;" id="imgA">
<!-- the initial picture to display -->
<a target="_new" href="img_off.jpg" onclick="this.blur();fadIn('imgA',100,1);return false">
<img src="img_on.jpg" style="height:658px;width:990px;border:0px;" /></a>
</div>

<script>
var isFading = 0;

function setOpacity(obj, opacity){opacity = (opacity == 100)?99.999:opacity;obj.style.filter = "alpha(opacity:"+opacity+")";obj.style.KHTMLOpacity = opacity/100;obj.style.MozOpacity = opacity/100;obj.style.opacity = opacity/100;};

function fadIn(objId,opacity,sc){if(((sc==1)&&(isFading == 0))||(sc==0)){isFading = 1;if (document.getElementById) {obj = document.getElementById(objId);if (opacity >= 0){setOpacity(obj, opacity);opacity -= 10;window.setTimeout("fadIn('"+objId+"',"+opacity+",0)", 100)}else{obj.style.display="none";isFading = 0}}}};

function fadOut(objId,opacity,sc){if(((sc==1)&&(isFading == 0))||(sc==0)){isFading = 1;if (document.getElementById){obj = document.getElementById(objId);obj.style.display="";if (opacity <= 100){setOpacity(obj, opacity);opacity += 10;window.setTimeout("fadOut('"+objId+"',"+opacity+",0)", 100)}else{isFading = 0}}}}

</script>

</div>

**Note: The important thing is to set the correct height and width for your images so that they will overlay/stack on top of one another properly.  To ensure a seamless fade I had to adjust the "top-margin" value.  You'll have to play with the value until you think it looks correct.  A sample of this can be found on my photography blog.

No comments:

Post a Comment