There’s more then one way to fill a storage unit

The Task

Create a storage calculator that allows visitors to select a specific storage unit from a list of unit sizes (e.g. 5×5, 5×10, etc.). Upon clicking on a option the page will show a cross section of the selected unit and animate it being filled with boxes, lamps, bookshelves and so on to give the visitor an ideal of what can fit in the unit. This was the task I received for a redesign that I was working on. At first I had no clue what I was going to do and thought I’d have to resort to Flash or something similar but then I stumbled upon the answer while doing some Googling.

Filling the storage unit
To see it in action click the image.

How’s it Done?

That’s the simple part, the developer that created this little gem must have subscribed to the KISS (Keep It Simple Stupid) principal because it really is.

First every piece of furniture is a PNG image with transparency. All images are absolutely positioned via CSS so that if we were to load the page without JavaScript enabled we would just see a full storage unit (image on the right).

Next up we apply some JavaScript that adjusts the images position vertically starting off screen and dropping till it hits the defined css bottom property value. The JavaScript part may seem complicated but jQuery makes this type of animation a breeze.

The Code

What follows below is the HTML portion of the code that defines a standard structure the jQuery UI will use to create a tabbed interface.

<div id="tabs">
<ul>
	<li><a href="#tabs-1">5' x 5'</a> ...</li>
	<li><a href="#tabs-2">5' x 10'</a> ...</li>
	<li><a href="#tabs-3">10' x 10'</a> ...</li>
	<li><a href="#tabs-4">10' x 15'</a> ...</li>
	<li><a href="#tabs-5">10' x 20'</a> ...</li>
	<li><a href="#tabs-6">10' x 25'</a> ...</li>
</ul>
<div id="tabs-1"> ... </div>
<div id="tabs-2"> ... </div>
<div id="tabs-3"> ... </div>
<div id="tabs-4"> ... </div>
<div id="tabs-5"> ... </div>
<div id="tabs-6"> ... </div>
</div>

Next up inside each one of the DIV’s with an id of tabs-N we define the contents of the tab and in this case the contents of the storage unit.

<div id="tabs-1">
	<img src="-assets/images/sizeGuide/5x5.png" alt="5x5" height="152px" style="padding:47px 0" />
	<img src="-assets/images/sizeGuide/bookshelf.png" alt="Bookshelf" style="height:104px; position:absolute; bottom:90px; left:286px" />
	<img src="-assets/images/sizeGuide/cridenza.png" alt="Cridenza" style="height:65px; position:absolute; bottom:80px; left:257px" />
	<img src="-assets/images/sizeGuide/tv.png" alt="TV" style="height:40px; position:absolute; bottom:126px; left:268px" />
	<img src="-assets/images/sizeGuide/smallBox.png" alt="Small Box" style="height:25px; position:absolute; bottom:77px; left:302px" />
	<img src="-assets/images/sizeGuide/lamp.png" alt="Lamp" style="height:32px; position:absolute; bottom:95px; left:312px" />
	<img src="-assets/images/sizeGuide/bicycle.png" alt="Bicycle" style="height:58px; position:absolute; bottom:73px; left:254px" />
</div>

The first image (5×5.png) is the storage unit cross section followed by one image for every piece of furniture in the unit. If you read the images from top to bottom you will notice they are ordered from the back of the unit to the front, the same order in which we want them to fall. Each image is also absolute positioned to its final resting place via a style tag.

Now the Javascript:

       $('#tabs img').each(function() {
		$(this).data('bottom', parseInt($(this).css('bottom')));
	});
	$('#tabs').tabs();

	$('#tabs').bind('tabsshow', dropFurniture);

	function dropFurniture(event, ui) {
		var i = 0;
		$('img', ui.panel).each(function() {
			$(this).css({bottom: ($(this).data('bottom') + 300) + 'px'}).delay(i*100).animate({bottom: $(this).data('bottom')});
			i++;
		});
	}
	dropFurniture(null, {panel: $('#tabs-1')});

Breaking down each block….

$('#tabs img').each(function() {
		$(this).data('bottom', parseInt($(this).css('bottom')));
	});

This code has jQuery select all img tags within an element with an id of tabs. The code then iterates over all matching elements and calls $.data to associate some data containing the images CSS bottom properties declared value.

$('#tabs').tabs();

This block creates the tabbed interface. (see jQuery UI tabs)

$('#tabs').bind('tabsshow', dropFurniture);

This block registers an event handler, in this case a function named dropFurniture, with the tabs tabsshow event. This event automatically gets raised every time a new tab is chosen.

function dropFurniture(event, ui) {
		var i = 0;
		$('img', ui.panel).each(function() {
			$(this).css({bottom: ($(this).data('bottom') + 300) + 'px'}).delay(i*100).animate({bottom: $(this).data('bottom')});
			i++;
		});
	}

The dropFurniture function does all the moving and is called whenever a new tab is selected. First it’ll get the currently active tab by referencing ui.panel of the passed in ui parameter and iterates over all images contained in it. Each of the images then gets moved up 300px from their currently defined CSS bottom property value (this moves them off the screen). The function then adds a delay before animating the image down to the previously defined CSS bottom property value. This animation causes the furniture pieces to appear to be falling from the sky.

dropFurniture(null, {panel: $('#tabs-1')});

The last line performs the animation when the page initially loads so that our first tab gets the animation.

In Closing

Putting it all together we get the effect we are looking for. Could we have done it another way, sure but this way works for the project. Now the hard part, having someone create all the furniture assets for us to use ;).

Note: This post contains code I did not create but did re-purpose for a project I was working on. I have no affiliation with marrickselfstorage.com and only link to it because it was the original example and the project discussed in this post has yet to go live.

Leave a Reply

Your email address will not be published. Required fields are marked *