Welcome to another carousel-based web tutorial.
This one's gonna be short, because we will be, in classic lazy-bastard programmer fashion, leveraging upon the code from the
last carousel-based web tutorial. This time, instead of making the images slide in and out of view, we'll make them
fade instead.
So let's go ahead and just copy all the code over. And then change all instances of "slide" to "fade". Which means that instead of calling them "slides", we will now call them "fades". Which is kind of lame, but it works for keeping things consistent, so there you go.
<!DOCTYPE html>
<html>
<head>
<title>Fade Carousel</title>
<style>
div {outline: 0px solid #FF0000;}
body
{
font-size: 12px;
font-family: verdana;
}
#carouselContainer
{
width: 800px;
height: 600px;
margin: 0 auto 0 auto;
}
.margin
{
width: 10%;
height: 100px;
float: left;
text-align: center;
font-size: 5em;
}
.margin input[type="button"]
{
color: rgba(0, 0, 0, 1);
cursor: pointer;
margin-top: 250px;
width: 50px;
height: 50px;
border-radius: 50%;
border: 0px solid red;
background-color: rgba(255, 200, 0, 1);
color: rgba(255, 255, 255, 1);
}
.margin input[type="button"]:hover
{
background-color: rgba(255, 200, 0, 0.5);
}
#viewport
{
width: 80%;
height: 100%;
float: left;
overflow: hidden;
border-radius: 15px;
}
#contentContainer
{
width: 200%;
height: 100%;
background-color: #004400;
}
.content
{
width: 50%;
height: 100%;
float: left;
background-color: #000044;
background-size: cover;
background-position: 50% 50%;
background-repeat: no-repeat;
padding-top: 1em;
}
.content div
{
padding: 1em;
background-color: rgba(255, 255, 255, 0.5);
color: rgba(0, 0, 0, 1);
font-weight: bold;
width: 80%;
border-radius: 5px;
margin: 0 auto 0 auto;
}
</style>
<script>
var carousel =
{
fades:
[
{
bg: "00.jpg",
content: "<div><h2>Phasellus ullamcorper</h2><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent fringilla molestie pellentesque. Aliquam auctor scelerisque mattis. Donec maximus ipsum non eros gravida suscipit. Sed vulputate massa orci, non placerat lectus suscipit mollis. Fusce faucibus lorem eu lectus mattis, et dictum urna semper. Maecenas massa magna, commodo at pulvinar ac, lacinia nec augue. Nullam pretium consectetur ultricies. In a mattis justo. Suspendisse potenti. Vivamus scelerisque, urna imperdiet faucibus facilisis, orci elit dictum ex, blandit rutrum metus diam eget mi. Phasellus ullamcorper eu purus eu venenatis. Nullam vestibulum dolor vel felis facilisis, ac rutrum tellus rutrum. Sed vehicula elementum erat, eget mattis tortor rhoncus a. Phasellus ut nisl volutpat, dictum lectus ut, dictum lectus.</p><h2>Quisque pharetra</h2><p>Lorem ipsum vel felis facilisis, ac rutrum tellus rutrum. Sed vehicula elementum erat, eget mattis tortor rhoncus a.</p><p>Vestibulum porta mattis quam a gravida. Aliquam quis quam nulla.</p></div>"
},
{
bg: "01.jpg",
content: "<div><h2>Phasellus mattis</h2><p>Lorem ipsum vel felis facilisis, ac rutrum tellus rutrum. Sed vehicula elementum erat, eget mattis tortor rhoncus a.</p></div>"
},
{
bg: "02.jpg",
content: "<div><h2>In diam nisi erat</h2><p>Vestibulum porta mattis quam a gravida. Aliquam quis quam nulla. Pellentesque nisi erat, elementum ut maximus sed, euismod vel dui. Curabitur vitae dui nec justo rhoncus imperdiet. In diam risus, egestas dictum viverra vel, pretium sed nisl.</p></div>"
},
{
bg: "03.jpg",
content: "<div><h2>Nullam ullamcorper</h2><p>Lorem ipsum scelerisque, urna imperdiet faucibus facilisis, orci elit dictum ex, blandit rutrum metus diam eget mi. Phasellus ullamcorper eu purus eu venenatis. Nullam vestibulum dolor vel felis facilisis, ac rutrum tellus rutrum. Sed vehicula elementum erat, eget mattis tortor rhoncus a. Phasellus ut nisl volutpat, dictum lectus ut, dictum lectus.</p><h2>Quisque pharetra</h2><p><img src='img/03.jpg' height='150' align='right' />Vestibulum porta mattis quam a gravida. Aliquam quis quam nulla. Pellentesque nisi erat, elementum ut maximus sed, euismod vel dui. Curabitur vitae dui nec justo rhoncus imperdiet. In diam risus, egestas dictum viverra vel, pretium sed nisl. Nam mi risus, imperdiet sed purus id, posuere feugiat nibh. Curabitur dignissim ipsum eget est pretium, ut luctus leo dapibus. Praesent in vehicula felis. Nullam quis faucibus justo. Praesent ac turpis tempor elit lobortis sodales laoreet pulvinar velit. Nam vel leo arcu. Cras magna nulla, lacinia in turpis vel, efficitur sagittis sem. Interdum et malesuada fames ac ante ipsum primis in faucibus. In congue consectetur lacus, ac venenatis elit gravida at.</p></div>"
},
{
bg: "04.jpg",
content: "<div><h2>Quisque pharetra</h2><p>Quisque eget aliquam urna. Integer tortor justo, fringilla ut diam in, ornare maximus sem. Nam dictum mauris nisl, id posuere sem sodales sit amet. Sed ac nulla ut nunc molestie vestibulum id a ipsum. Duis nec elementum libero. Etiam porttitor turpis eu venenatis porta. Quisque pharetra diam vel dui porta luctus. Duis sed odio viverra, molestie orci et, hendrerit erat. Duis ut tortor nec orci suscipit finibus nec non massa. </p></div>"
}
],
currentFadeIndex: 0,
contentContainer: undefined,
c0: undefined,
c1: undefined,
canMove: true,
begin: function()
{
this.contentContainer = document.getElementById("contentContainer");
this.c0 = document.getElementById("content0");
this.c1 = document.getElementById("content1");
this.setContent(this.currentFadeIndex + 1, "left");
setInterval
(
function()
{
carousel.animateFader();
},
5000
);
},
animateFader: function()
{
if (this.canMove)
{
this.fade("left");
}
},
fade: function(dir)
{
var nextFade;
var currentMarginLeft;
var nextMarginLeft;
this.setTransitionSpeed(0);
if (dir == "left")
{
if (this.currentFadeIndex == this.fades.length - 1)
{
nextFade = 0;
}
else
{
nextFade = this.currentFadeIndex + 1;
}
currentMarginLeft = 0;
nextMarginLeft = -100;
}
if (dir == "right")
{
if (this.currentFadeIndex == 0)
{
nextFade = this.fades.length - 1;
}
else
{
nextFade = this.currentFadeIndex - 1;
}
currentMarginLeft = -100;
nextMarginLeft = 0;
}
this.setMargin(currentMarginLeft);
this.setContent(nextFade, dir);
setTimeout
(
function()
{
carousel.setTransitionSpeed(1);
},
250
);
setTimeout
(
function()
{
carousel.setMargin(nextMarginLeft);
carousel.currentFadeIndex = nextFade;
},
500
);
setTimeout
(
function()
{
carousel.canMove = true;
},
5000
);
},
setTransitionSpeed: function(interval)
{
this.contentContainer.style.webKitTransition = interval + "s all";
this.contentContainer.style.transition = interval + "s all";
},
setMargin: function(margin)
{
this.contentContainer.style.marginLeft = margin + "%";
},
setContent: function(next, dir)
{
if (dir == "left")
{
this.c0.innerHTML = this.fades[this.currentFadeIndex].content;
this.c0.style.backgroundImage = "url(img/" + this.fades[this.currentFadeIndex].bg + ")";
this.c1.innerHTML = this.fades[next].content;
this.c1.style.backgroundImage = "url(img/" + this.fades[next].bg + ")";
}
if (dir == "right")
{
this.c0.innerHTML = this.fades[next].content;
this.c0.style.backgroundImage = "url(img/" + this.fades[next].bg + ")";
this.c1.innerHTML = this.fades[this.currentFadeIndex].content;
this.c1.style.backgroundImage = "url(img/" + this.fades[this.currentFadeIndex].bg + ")";
}
},
faderButtonClick: function(dir)
{
this.canMove = false;
this.fade(dir);
}
}
</script>
</head>
<body onload = "carousel.begin();">
<div id="carouselContainer">
<div class="margin">
<input type="button" onclick="carousel.faderButtonClick('left')" value="◄"/>
</div>
<div id="viewport">
<div id="contentContainer">
<div id="content0" class="content"></div>
<div id="content1" class="content"></div>
</div>
</div>
<div class="margin">
<input type="button" onclick="carousel.faderButtonClick('right')" value="►"/>
</div>
</div>
</body>
</html>
Set divs to have that
red outline, because we don't want to be developing blind.
div {outline: 1px solid #FF0000;}
There will be no change to the HTML, and very little to the CSS. For the
contentContainer div, instead of having it 200% of its parent, it now fits the parent's width exactly at 100%. For the
content CSS class, we remove the
background-color property because now we're doing a fade-in/fade-out thing and we
don't want the background to show up unexpectedly. Also, change its width to 100%.
#contentContainer
{
width: 100%;
height: 100%;
background-color: #004400;
}
.content
{
width: 100%;
height: 100%;
float: left;
/*background-color: #000044;*/
background-size: cover;
background-position: 50% 50%;
background-repeat: no-repeat;
padding-top: 1em;
}
And add a new rule for
content0, setting its
margin-right property to negative 100%. This means that the divs
content0 and
content1 will overlap each other within
contentContainer.
.content
{
width: 100%;
height: 100%;
float: left;
background-size: cover;
background-position: 50% 50%;
background-repeat: no-repeat;
padding-top: 1em;
}
#content0
{
margin-right: -100%;
}
The result of this is that now your slide carousel doesn't show the next slide while sliding. Remember now
content0 and
content1 overlap and
contentContainer is no longer twice as wide as
viewport? That's OK, because we no longer want it to slide and that's the next thing we will take care of.
The JavaScript
The
begin() method of the carousel object operates on the same principle as the Slide Carousel's, and no change needs to be made here save for the naming of the callback, which is now
animateFader().
animateFader(), in turn, has no change except that the callback is now
fade() rather than
slide(). It's
fade() that we have to tweak.
The
If blocks that determine which
slide fade comes next, is logically the same, so no change there. However, we no longer want to change the
margin-left property. Instead, we want to change the
opacity property. So let's remove the variables. And instead of callng the
setMargin() method, we call the
setOpacity() method, passing in 100 and 0 as arguments, in different orders. You'll see why later.
Also remove the
dir argument for the call to
setContent().
fade: function(dir)
{
var nextFade;
//var currentMarginLeft;
//var nextMarginLeft;
this.setTransitionSpeed(0);
if (dir == "left")
{
if (this.currentFadeIndex == this.fades.length - 1)
{
nextFade = 0;
}
else
{
nextFade = this.currentFadeIndex + 1;
}
//currentMarginLeft = 0;
//nextMarginLeft = -100;
}
if (dir == "right")
{
if (this.currentFadeIndex == 0)
{
nextFade = this.fades.length - 1;
}
else
{
nextFade = this.currentFadeIndex - 1;
}
//currentMarginLeft = -100;
//nextMarginLeft = 0;
}
//this.setMargin(currentMarginLeft);
this.setOpacity(100, 0);
this.setContent(nextFade/*, dir*/);
setTimeout
(
function()
{
carousel.setTransitionSpeed(1);
},
250
);
setTimeout
(
function()
{
//carousel.setMargin(nextMarginLeft);
carousel.setOpacity(0, 100);
carousel.currentFadeIndex = nextFade;
},
500
);
setTimeout
(
function()
{
carousel.canMove = true;
},
5000
);
},
Next, we rename the
setMargin() method to
setOpacity(). It will now accept two parameters,
c0_opacity and
c1_opacity.
setOpacity: function(c0_opacity, c1_opacity)
{
//this.contentContainer.style.marginLeft = margin + "%";
},
In here, we want
c0 and
c1 to take on the opacities specified by their respective arguments. So if one is 100 and the other is 0, and there's a transition speed of more than 0 involved, it will look like one is fading out in favor of the other! Now you see why the need for the 100 and 0 values passed to the
setOpacity() method earlier?
setOpacity: function(c0_opacity, c1_opacity)
{
//this.contentContainer.style.marginLeft = margin + "%";
this.c0.style.filter = "opacity(" + c0_opacity + "%)";
this.c1.style.filter = "opacity(" + c1_opacity + "%)";
},
The
setTransitionSpeed() method also needs changing. Remove the code inside.
setTransitionSpeed: function(interval)
{
//this.contentContainer.style.webKitTransition = interval + "s all";
//this.contentContainer.style.transition = interval + "s all";
},
Instead of altering the properties of
contentContainer, we will alter the properties of
content0 and
content1.
setTransitionSpeed: function(interval)
{
//this.contentContainer.style.webKitTransition = interval + "s all";
//this.contentContainer.style.transition = interval + "s all";
this.c0.style.webKitTransition = interval + "s all";
this.c0.style.transition = interval + "s all";
this.c1.style.webKitTransition = interval + "s all";
this.c1.style.transition = interval + "s all";
},
OK, now we can modify the
setContent() method. Get rid of all the code inside because we won't need it. Remember a fade is different from a slide - whether you're transitioning through the array in ascending or descending order, visually it's all the same. In a slide motion, you gave to cater for sliding left and right; in a fade motion, you simply adjust the opacity. You also won't need
dir (as mentioned, it no longer matters what direction the animation is in), so remove it..
setContent: function(next/*, dir*/)
{
/*if (dir == "left")
{
this.c0.innerHTML = this.fades[this.currentFadeIndex].content;
this.c0.style.backgroundImage = "url(img/" + this.fades[this.currentFadeIndex].bg + ")";
this.c1.innerHTML = this.fades[next].content;
this.c1.style.backgroundImage = "url(img/" + this.fades[next].bg + ")";
}
if (dir == "right")
{
this.c0.innerHTML = this.fades[next].content;
this.c0.style.backgroundImage = "url(img/" + this.fades[next].bg + ")";
this.c1.innerHTML = this.fades[this.currentFadeIndex].content;
this.c1.style.backgroundImage = "url(img/" + this.fades[this.currentFadeIndex].bg + ")";
}*/
},
What you need to do is ensure that
content0 shows the current fade, and
content1 shows the next fade.
Always.
setContent: function(next/*, dir*/)
{
/*if (dir == "left")
{
this.c0.innerHTML = this.fades[this.currentFadeIndex].content;
this.c0.style.backgroundImage = "url(img/" + this.fades[this.currentFadeIndex].bg + ")";
this.c1.innerHTML = this.fades[next].content;
this.c1.style.backgroundImage = "url(img/" + this.fades[next].bg + ")";
}
if (dir == "right")
{
this.c0.innerHTML = this.fades[next].content;
this.c0.style.backgroundImage = "url(img/" + this.fades[next].bg + ")";
this.c1.innerHTML = this.fades[this.currentFadeIndex].content;
this.c1.style.backgroundImage = "url(img/" + this.fades[this.currentFadeIndex].bg + ")";
}*/
this.c0.innerHTML = this.fades[this.currentFadeIndex].content;
this.c0.style.backgroundImage = "url(img/" + this.fades[this.currentFadeIndex].bg + ")";
this.c1.innerHTML = this.fades[next].content;
this.c1.style.backgroundImage = "url(img/" + this.fades[next].bg + ")";
},
Remember how I said we didn't have to change the
begin() method? That wasn't exactly true.
setContent() now only accepts a single argument, so you have to remove the second argument. Also, since we're no longer preparing for a slide left motion, we can take away the plus one from
currentFadeIndex.
begin: function()
{
this.contentContainer = document.getElementById("contentContainer");
this.c0 = document.getElementById("content0");
this.c1 = document.getElementById("content1");
this.setContent(this.currentFadeIndex/* +1, "left"*/);
setInterval
(
function()
{
carousel.animateFader();
},
5000
);
},
Can you see the fade-in/fade-out effect?
Remove the
red outline now, and things will look even prettier.
div {outline: 0px solid #FF0000;}
You might want to increase the transition speed here to make it fade even slower so the user can properly appreciate it. But be careful not to set it to a value greater or equal to the interval specified in
animateFader(). Because that would be just messy.
setTimeout
(
function()
{
carousel.setTransitionSpeed(3);
},
250
);
That's it, we're done!
I promised this would be short.
Unfortunately, this tutorial will make a whole lot more sense if you were present during the previous one. But this tutorial was maybe 80% similar to the last one and I hate repeating myself, so...
Fading out,
T___T