jQuery: how to split images on slideshows

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.

Demo

Live demo

Download

ZIP file

This entry was posted in by Gabriele Romanato. Bookmark the permalink.

2 thoughts on “jQuery: how to split images on slideshows”

Leave a Reply

Note: Only a member of this blog may post a comment.