Animated slideshows are simply jQuery slideshows where some animations take place on each slide. The problem is that when we have to deal with complex animations we're forced to use complex CSS styles in our code for each slide. When you have several slides this may become troublesome. For that reason we can bind directly our styles and easing algorithms on the animated elements thanks to the custom HTML5 data attributes.
Take for example the following markup:
<div id="slideshow">
<div id="slideshow-wrapper">
<div class="slide">
<img src="1.jpg" alt="Product 1"
data-from='{"top": "-100px", "left":"-100px"}' data-to='{"top":"20px","left":"50px"}' data-easing="easeOutBounce"/>
<p class="slide-caption">Product 1</p>
</div>
<div class="slide">
<img src="2.jpg" alt="Product 2"
data-from='{"bottom": "-100px", "left":"0"}' data-to='{"bottom":"20px","left":"60px"}' data-easing="easeOutElastic"/>
<p class="slide-caption">Product 2</p>
</div>
<div class="slide">
<img src="3.jpg" alt="Product 3"
data-from='{"right": "-300px", "top":"50px"}' data-to='{"right":"240px","top":"80px"}' data-easing="easeOutExpo"/>
<p class="slide-caption">Product 3</p>
</div>
<img src="loading.gif" id="loader" alt=""/>
</div>
<div id="slideshow-nav">
<a href="#" data-slide="0">1</a>
<a href="#" data-slide="1">2</a>
<a href="#" data-slide="2">3</a>
</div>
</div>
Our data attributes are as follows:
data-from
: the initial CSS styles for the animated elementdata-to
: the final CSS styles for the animated elementdata-easing
: the easing algorithm to be used in each animationdata-slide
: the numerical index of each slide in the DOM
We start with the following CSS styles:
#slideshow {
width: 100%;
max-width: 500px;
margin: 2em auto;
font: 100%/1 Georgia, serif;
}
#slideshow-wrapper {
height: 300px;
border: 4px double #ddd;
position: relative;
}
div.slide {
width: 100%;
height: 100%;
position: relative;
display: none;
overflow: hidden;
}
.slide-caption {
margin: 0;
background: rgba(0, 0, 0, 0.7);
color: #fff;
text-align: center;
position: absolute;
width: 200px;
height: 100%;
line-height: 300px;
top: 0;
right: -200px;
}
#loader {
position: absolute;
top: 50%;
left: 50%;
margin: -33px 0 0 -33px;
display: none;
}
div.slide img {
position: absolute;
display: none;
}
#slideshow-nav {
margin: 1em 0;
text-align: center;
}
#slideshow-nav a {
color: #fff;
background: #000;
text-decoration: none;
display: inline-block;
width: 2em;
height: 2em;
line-height: 2;
margin-right: 1em;
}
With jQuery we're going to use the $.parseJSON()
utility method to turn attribute data into JavaScript objects to be used with the css()
and animate()
methods:
var Slideshow = {
utils: {
animateSlide: function(slide) {
this.resetSlides();
$('#loader').fadeIn(600, function() {
$(this).delay(600).fadeOut(600, function() {
slide.show().siblings('div.slide').hide();
var $img = $('img[data-from]', slide);
var $caption = $('p.slide-caption', slide);
var to = $img.attr('data-to');
var toStyles = $.parseJSON(to);
var easing = $img.data('easing');
$img.show().animate(toStyles, 800, easing, function() {
$caption.animate({right: 0}, 600, 'easeOutExpo');
});
});
});
},
resetSlides: function() {
Slideshow.fn.setImages();
$('p.slide-caption').css('right', -200);
}
},
fn: {
setImages: function() {
$('img[data-from]', '#slideshow').each(function() {
var $img = $(this);
$img.hide();
var from = $img.attr('data-from');
var fromStyles = $.parseJSON(from);
$img.css(fromStyles);
});
},
navigate: function() {
$('a', '#slideshow-nav').on('click', function(evt) {
evt.preventDefault();
var $a = $(this);
var $slide = $('div.slide').eq($a.data('slide'));
Slideshow.utils.animateSlide($slide);
});
}
},
init: function() {
for(var p in this.fn) {
if( typeof this.fn[p] === 'function') {
this.fn[p]();
}
}
}
};
$(function() {
Slideshow.init();
});
You can see the demo on this page.