How to create a mosaic transition effect between two photos using jQuery

While playing around with some jQuery effects, I ended up building a mosaic transition effect between two photos, and I decided to wrap it up in a tutorial and share it with you ([download id=”15″ format=”1″]). First, have a look at the demo to check what we will end up building. There is another version of the effect as well.

To begin with, we will use two photos with the same dimensions. The only HTML code we’ll need (apart from loading the scripts) is an html element (it can be whatever you want; I’m using a div) that we will use as our container. It should have a unique id; I named it “mosaic”.

The only piece of CSS code we’ll have to write is the following (replace the images’ filenames with yours):

	background-image: url('bottom.jpg');

#mosaic span.hover
	float: left;
	background-image: url('top.jpg');

Now, let’s talk JavaScript.

First of all, we’ll include almost all of the code inside a $(document).ready function. We begin by declaring and initialising some variables: width and height contain our photos’ dimensions, elements is an array which will hold the elements we’ll create that will form the overlay of the base photo, count will be used later to help us iterate through the elements array, and el holds the HTML element we are using as a container. We also set the width and height of the element to the dimensions we just specified.

var width = 640;
var height = 480;

elements = new Array();
count = 0;
var el = $('#mosaic');

The next step is to specify the number of the horizontal and vertical pieces we want our mosaic to consist from. Then, based on this selection, we calculate the total number of pieces, as well as their dimensions.

var horizontal_pieces = 8;
var vertical_pieces = 6;
total_pieces = horizontal_pieces * vertical_pieces;

var box_width = width / horizontal_pieces;
var box_height = height / vertical_pieces;

Afterwards, based on the above values, we create a set of span elements (assigning unique IDs to them), which will act as the tiles that will form the mosaic, and will be used to perform the transition effect.

Since we want the tiles of the mosaic to form a complete photo, we will use the photo as a sprite. We already specified it as the background of all the span elements using the #mosaic span.hover CSS rule, so we just need to make a few calculations to calculate which part of the photo will need to be visible in each element, and modify their background-position to accomplish that. We append all of the newly created elements to the container, and also add them to the elements array, so they can be retrieved later.

var vertical_position = 0;

for (i=0; i<total_pieces; i++)
	var tempEl = $('<span class="hover" id="hover-' + i + '"></span>');
	var horizontal_position = (i % horizontal_pieces) * box_width;
	if(i > 0 && i % horizontal_pieces == 0)
		vertical_position += box_height;

	tempEl.css('background-position', '-' + horizontal_position + 'px -' + vertical_position + 'px');

Finally, we apply the dimensions we calculated before in all of the span elements, and we call the toggleDisplay function (I’ll explain it in a bit) every 100 milliseconds.

$('#mosaic .hover').width(box_width).height(box_height);
setInterval(toggleDisplay, 100);

This wraps-up what is included in the $(document).ready function; we’ll continue with the toggleDisplay function I mentioned before.

It’s a very simple function, which grabs the next item set to be checked from the elements array (based on the count variable), and toggles its opacity value. Finally, it iterates the count variable.

function toggleDisplay()
	var tempEl = elements[count];
	var opacity = tempEl.css('opacity');

	if(opacity == 0)
		tempEl.animate({ opacity: 1 })
		tempEl.animate({ opacity: 0 })

	count = (count + 1) % total_pieces;

Apart from the above, by performing some minor alterations to the code, we can change the sequence of the transition to accomplish other effects. For example, by shuffling the elements array randomly, we can achieve this effect.

Updated on 1st of May, 2013: Based on the comments by R, I added a third demo.

[download id=”15″ format=”1″] | demo (version 1) | demo (version 2) | demo (version 3)

Photo by ~sufined