Splitting and dividing images on a jQuery slideshow is not so difficult as it could seem at a first glance. In fact, if you know the technique that works behind the scenes, you'll probably end up with realizing how this feature is simple in its implementation. In a nutshell: it's only a matter of layers and background images. Let's see the details.
The markup
We have a very simple and common slideshow structure:
<div id="slideshow"> <div id="slideshow-wrapper"> <div class="slide"> <img src="img/1.jpg" alt="" /> </div> <div class="slide"> <img src="img/2.jpg" alt="" /> </div> <div class="slide"> <img src="img/3.jpg" alt="" /> </div> <div class="slide"> <img src="img/4.jpg" alt="" /> </div> </div> </div>
Each image is 1150 x 400 pixels wide. We have to create a grid made up of 40 blocks and 4 rows to be applied on each slide. Each row is made up of 10 blocks. In turn, each block is 115 x 100 pixels wide, so (115 x 10) and (100 x 4) give us the total image dimensions. Here comes the trick: each of these blocks will have the current image as its background image, but with different x and y values for the CSS background-position
property. Once set the blocks, it's easy to animate them with jQuery.
The CSS styles
Our CSS styles are as follows:
#slideshow { margin: 2em auto; width: 90%; max-width: 1150px; height: 400px; border: 5px solid #565656; overflow: hidden; position: relative; } #slideshow-wrapper { width: 4600px; height: 400px; position: relative; background: #ccc; } #slideshow-wrapper img { width: 1150px; height: 400px; display: none; } div.slide { float: left; width: 1150px; height: 400px; position: relative; } div.overlay { width: 1150px; height: 400px; position: absolute; top: 0; left: 0; } div.row { height: 100px; position: relative; } div.piece { height: 100px; width: 115px; background-repeat: no-repeat; float: left; display: none; }
The jQuery code
We start with a singleton object and we declare the properties and variables used throughout its namespace:
var Slideshow = new function() { var slideshow = document.getElementById('slideshow'), wrapper = $('#slideshow-wrapper', slideshow), slides = $('div.slide', wrapper), pieces = $('div.piece', slides), index = -1, timer = null; // continues }();
Then we split each slide into pieces using the following private method:
var Slideshow = new function() { var slideshow = document.getElementById('slideshow'), wrapper = $('#slideshow-wrapper', slideshow), slides = $('div.slide', wrapper), pieces = $('div.piece', slides), index = -1, timer = null; var insertBlocks = function() { slides.each(function() { var slide = $(this); $('<div class="overlay"/>').appendTo(slide); var block = '<div class="row">' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '</div>'; for(var i = 0; i < 4; i += 1) { $(block).appendTo($('div.overlay', slide)); } }); }; // continues }();
Then we set the background images:
var Slideshow = new function() { var slideshow = document.getElementById('slideshow'), wrapper = $('#slideshow-wrapper', slideshow), slides = $('div.slide', wrapper), pieces = $('div.piece', slides), index = -1, timer = null; var insertBlocks = function() { slides.each(function() { var slide = $(this); $('<div class="overlay"/>').appendTo(slide); var block = '<div class="row">' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '</div>'; for(var i = 0; i < 4; i += 1) { $(block).appendTo($('div.overlay', slide)); } }); }; var setBackgroundImages = function() { slides.each(function() { var slide = $(this); var src = $('img', slide).attr('src'); var pieces = $('div.piece', slide); pieces.css('backgroundImage', 'url(' + src + ')'); pieces.eq(0).css('backgroundPosition', '0px 0px'); pieces.eq(1).css('backgroundPosition', '-115px 0px'); pieces.eq(2).css('backgroundPosition', '-230px 0px'); pieces.eq(3).css('backgroundPosition', '-345px 0px'); pieces.eq(4).css('backgroundPosition', '-460px 0px'); pieces.eq(5).css('backgroundPosition', '-575px 0px'); pieces.eq(6).css('backgroundPosition', '-690px 0px'); pieces.eq(7).css('backgroundPosition', '-805px 0px'); pieces.eq(8).css('backgroundPosition', '-925px 0px'); pieces.eq(9).css('backgroundPosition', '-1040px 0px'); pieces.eq(10).css('backgroundPosition', '0px -100px'); pieces.eq(11).css('backgroundPosition', '-115px -100px'); pieces.eq(12).css('backgroundPosition', '-230px -100px'); pieces.eq(13).css('backgroundPosition', '-345px -100px'); pieces.eq(14).css('backgroundPosition', '-460px -100px'); pieces.eq(15).css('backgroundPosition', '-575px -100px'); pieces.eq(16).css('backgroundPosition', '-690px -100px'); pieces.eq(17).css('backgroundPosition', '-805px -100px'); pieces.eq(18).css('backgroundPosition', '-925px -100px'); pieces.eq(19).css('backgroundPosition', '-1040px -100px'); pieces.eq(20).css('backgroundPosition', '0px -200px'); pieces.eq(21).css('backgroundPosition', '-115px -200px'); pieces.eq(22).css('backgroundPosition', '-230px -200px'); pieces.eq(23).css('backgroundPosition', '-345px -200px'); pieces.eq(24).css('backgroundPosition', '-460px -200px'); pieces.eq(25).css('backgroundPosition', '-575px -200px'); pieces.eq(26).css('backgroundPosition', '-690px -200px'); pieces.eq(27).css('backgroundPosition', '-805px -200px'); pieces.eq(28).css('backgroundPosition', '-925px -200px'); pieces.eq(29).css('backgroundPosition', '-1040px -200px'); pieces.eq(30).css('backgroundPosition', '0px -300px'); pieces.eq(31).css('backgroundPosition', '-115px -300px'); pieces.eq(32).css('backgroundPosition', '-230px -300px'); pieces.eq(33).css('backgroundPosition', '-345px -300px'); pieces.eq(34).css('backgroundPosition', '-460px -300px'); pieces.eq(35).css('backgroundPosition', '-575px -300px'); pieces.eq(36).css('backgroundPosition', '-690px -300px'); pieces.eq(37).css('backgroundPosition', '-805px -300px'); pieces.eq(38).css('backgroundPosition', '-925px -300px'); pieces.eq(39).css('backgroundPosition', '-1040px -300px'); }); }; // continues }();
It's verbose but doing so is the best way to help you understand how it works. Now we have to animate the slideshow:
var Slideshow = new function() { var slideshow = document.getElementById('slideshow'), wrapper = $('#slideshow-wrapper', slideshow), slides = $('div.slide', wrapper), pieces = $('div.piece', slides), index = -1, timer = null; var insertBlocks = function() { slides.each(function() { var slide = $(this); $('<div class="overlay"/>').appendTo(slide); var block = '<div class="row">' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '</div>'; for(var i = 0; i < 4; i += 1) { $(block).appendTo($('div.overlay', slide)); } }); }; var setBackgroundImages = function() { slides.each(function() { var slide = $(this); var src = $('img', slide).attr('src'); var pieces = $('div.piece', slide); pieces.css('backgroundImage', 'url(' + src + ')'); pieces.eq(0).css('backgroundPosition', '0px 0px'); pieces.eq(1).css('backgroundPosition', '-115px 0px'); pieces.eq(2).css('backgroundPosition', '-230px 0px'); pieces.eq(3).css('backgroundPosition', '-345px 0px'); pieces.eq(4).css('backgroundPosition', '-460px 0px'); pieces.eq(5).css('backgroundPosition', '-575px 0px'); pieces.eq(6).css('backgroundPosition', '-690px 0px'); pieces.eq(7).css('backgroundPosition', '-805px 0px'); pieces.eq(8).css('backgroundPosition', '-925px 0px'); pieces.eq(9).css('backgroundPosition', '-1040px 0px'); pieces.eq(10).css('backgroundPosition', '0px -100px'); pieces.eq(11).css('backgroundPosition', '-115px -100px'); pieces.eq(12).css('backgroundPosition', '-230px -100px'); pieces.eq(13).css('backgroundPosition', '-345px -100px'); pieces.eq(14).css('backgroundPosition', '-460px -100px'); pieces.eq(15).css('backgroundPosition', '-575px -100px'); pieces.eq(16).css('backgroundPosition', '-690px -100px'); pieces.eq(17).css('backgroundPosition', '-805px -100px'); pieces.eq(18).css('backgroundPosition', '-925px -100px'); pieces.eq(19).css('backgroundPosition', '-1040px -100px'); pieces.eq(20).css('backgroundPosition', '0px -200px'); pieces.eq(21).css('backgroundPosition', '-115px -200px'); pieces.eq(22).css('backgroundPosition', '-230px -200px'); pieces.eq(23).css('backgroundPosition', '-345px -200px'); pieces.eq(24).css('backgroundPosition', '-460px -200px'); pieces.eq(25).css('backgroundPosition', '-575px -200px'); pieces.eq(26).css('backgroundPosition', '-690px -200px'); pieces.eq(27).css('backgroundPosition', '-805px -200px'); pieces.eq(28).css('backgroundPosition', '-925px -200px'); pieces.eq(29).css('backgroundPosition', '-1040px -200px'); pieces.eq(30).css('backgroundPosition', '0px -300px'); pieces.eq(31).css('backgroundPosition', '-115px -300px'); pieces.eq(32).css('backgroundPosition', '-230px -300px'); pieces.eq(33).css('backgroundPosition', '-345px -300px'); pieces.eq(34).css('backgroundPosition', '-460px -300px'); pieces.eq(35).css('backgroundPosition', '-575px -300px'); pieces.eq(36).css('backgroundPosition', '-690px -300px'); pieces.eq(37).css('backgroundPosition', '-805px -300px'); pieces.eq(38).css('backgroundPosition', '-925px -300px'); pieces.eq(39).css('backgroundPosition', '-1040px -300px'); }); }; var autoSlide = function() { timer = setInterval(function() { index++; if(index == (slides.length - 1)) { index = -1; } wrapper.animate({ left: - slides.eq(index).position().left }, 0, function() { var slide = slides.eq(index); var parts = $('div.piece', slide); var counter = -1; var slicer = null; slicer = setInterval(function() { counter++; if(counter == (parts.length)) { clearInterval(slicer); parts.fadeOut(); } parts.eq(counter).fadeIn(75); }, 75); }); }, 3000); }; // continues }();
Finally, we create an initialization public method:
var Slideshow = new function() { var slideshow = document.getElementById('slideshow'), wrapper = $('#slideshow-wrapper', slideshow), slides = $('div.slide', wrapper), pieces = $('div.piece', slides), index = -1, timer = null; var insertBlocks = function() { slides.each(function() { var slide = $(this); $('<div class="overlay"/>').appendTo(slide); var block = '<div class="row">' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '<div class="piece"></div>' + '</div>'; for(var i = 0; i < 4; i += 1) { $(block).appendTo($('div.overlay', slide)); } }); }; var setBackgroundImages = function() { slides.each(function() { var slide = $(this); var src = $('img', slide).attr('src'); var pieces = $('div.piece', slide); pieces.css('backgroundImage', 'url(' + src + ')'); pieces.eq(0).css('backgroundPosition', '0px 0px'); pieces.eq(1).css('backgroundPosition', '-115px 0px'); pieces.eq(2).css('backgroundPosition', '-230px 0px'); pieces.eq(3).css('backgroundPosition', '-345px 0px'); pieces.eq(4).css('backgroundPosition', '-460px 0px'); pieces.eq(5).css('backgroundPosition', '-575px 0px'); pieces.eq(6).css('backgroundPosition', '-690px 0px'); pieces.eq(7).css('backgroundPosition', '-805px 0px'); pieces.eq(8).css('backgroundPosition', '-925px 0px'); pieces.eq(9).css('backgroundPosition', '-1040px 0px'); pieces.eq(10).css('backgroundPosition', '0px -100px'); pieces.eq(11).css('backgroundPosition', '-115px -100px'); pieces.eq(12).css('backgroundPosition', '-230px -100px'); pieces.eq(13).css('backgroundPosition', '-345px -100px'); pieces.eq(14).css('backgroundPosition', '-460px -100px'); pieces.eq(15).css('backgroundPosition', '-575px -100px'); pieces.eq(16).css('backgroundPosition', '-690px -100px'); pieces.eq(17).css('backgroundPosition', '-805px -100px'); pieces.eq(18).css('backgroundPosition', '-925px -100px'); pieces.eq(19).css('backgroundPosition', '-1040px -100px'); pieces.eq(20).css('backgroundPosition', '0px -200px'); pieces.eq(21).css('backgroundPosition', '-115px -200px'); pieces.eq(22).css('backgroundPosition', '-230px -200px'); pieces.eq(23).css('backgroundPosition', '-345px -200px'); pieces.eq(24).css('backgroundPosition', '-460px -200px'); pieces.eq(25).css('backgroundPosition', '-575px -200px'); pieces.eq(26).css('backgroundPosition', '-690px -200px'); pieces.eq(27).css('backgroundPosition', '-805px -200px'); pieces.eq(28).css('backgroundPosition', '-925px -200px'); pieces.eq(29).css('backgroundPosition', '-1040px -200px'); pieces.eq(30).css('backgroundPosition', '0px -300px'); pieces.eq(31).css('backgroundPosition', '-115px -300px'); pieces.eq(32).css('backgroundPosition', '-230px -300px'); pieces.eq(33).css('backgroundPosition', '-345px -300px'); pieces.eq(34).css('backgroundPosition', '-460px -300px'); pieces.eq(35).css('backgroundPosition', '-575px -300px'); pieces.eq(36).css('backgroundPosition', '-690px -300px'); pieces.eq(37).css('backgroundPosition', '-805px -300px'); pieces.eq(38).css('backgroundPosition', '-925px -300px'); pieces.eq(39).css('backgroundPosition', '-1040px -300px'); }); }; var autoSlide = function() { timer = setInterval(function() { index++; if(index == (slides.length - 1)) { index = -1; } wrapper.animate({ left: - slides.eq(index).position().left }, 0, function() { var slide = slides.eq(index); var parts = $('div.piece', slide); var counter = -1; var slicer = null; slicer = setInterval(function() { counter++; if(counter == (parts.length)) { clearInterval(slicer); parts.fadeOut(); } parts.eq(counter).fadeIn(75); }, 75); }); }, 3000); }; this.init = function() { insertBlocks(); setBackgroundImages(); autoSlide(); }; }();
And we kick things off:
$(function() { Slideshow.init(); });
You can see the demo below.
so cool...so split :D
Great Stuff!