jQuery realistic filling effect
July 13, 2010
Intro
After spending some time playing with the superb jQuery and jQuery UI functions used in many of the tutorials online, I got thinking about other ways this same technique could be used, especially the movement of background images to create realistic real life effects.
The original thought were purely to use a background-image translation to mimic something like a cup filling with water, the original idea was to use two images, one static, with a transparent inner, and one 'moving' component which would travel undearneath and show through the transpaent areas of the background image.
In principle, and with purely 2D images this is a sound concept, however when tried with a 'realistic' image, I discovered some caveats which would prevent the method from working in many situations, we anticipated difficulties when the foreground was clear or clear 'ish', a neccesity to allow the moving image to show through and the background of the site was different to that which you wanted to show in the bottle.
An example of this is found on the 'demo page' - Figure 1
Another idea centred around creating a realistic top layer and moving that over a static background, this would work fine when dealing with objects that have a consistent horizontal width, such us a baked bean can, but with anything more complex the fact we were just sliding an image upward or downward would become apparent.
Principle
So, what's an effective way to create jQuery driven animations with the use of realistic images? One way is to use a realistic static background image combined with a realistic static foreground image and have the moving 'fill' image slide up and down between the two.
Initially I though that three components might be overkill, but on thinking a bit further I came up with a concise semantic HTML structure which could lend itself to something like site navigation which allowed the three layers to exist on top of each other using nothing more advanced than clever use of image transparency (Sorry IE6 users!)
The end result can be seen here: 'demo page' - Figure 2 (bear in mind this was a quick construct!)
Method
The solution was remarkably simple, I remembered some sensible advice given by 'Dan Cederholm' in his 'Handcrafted CSS' book around limiting usage of HTML elements to the minimum number needed to present the number of styling options required. Specifically how you'd need at least two to generate a sliding doors type effect (one per background image). With this is mind, I decided all I'd need was a HTML structure with allowed at least 3 elements to be placed on top of each other. In order to minimise the need to next several items using custom divs I opted to use native HTML elements, namely a list item, a span, and an anchor.
HTML
<div id="wine">
<ul>
<li>
<span>
<a></a>
</span>
</li>
</ul>
</div>
CSS
The CSS for the three elements here is as simple as the HTML itself, it merely assigns a background image to each of the 'li', 'span' and 'a'.
#wine ul li {
background: url("../img/bottleSlide_bottom.png") 0 0 no-repeat;
width: 200px;
height: 300px;
}
#wine ul li span {
background: url("../img/bottleSlide_middle.png") 0 300px no-repeat;
width: 200px;
height: 300px;
display: block;
}
#wine ul li span a {
background: url("../img/bottleSlide_top.png") 0 0 no-repeat;
width: 200px;
height: 300px;
display: block;
}
The 'bottleSlide_middle.png' image is purely one colour and could technically be achieved by setting a background colour.
The reason I've left this is as an image for the time being is that in the future I would like to expand this example to not only include movement on one axis, but to add in a translation accross the Y-axis, to give the impression that the contents of the item filling is not filling in a straight line, but being 'poured' or some other equally realistic method of filling!
This method relies on using the jQuery 'animate()' function to move a background image; to facilitate this we need to include the excellent background image plugin found at 'http://plugins.jquery.com'. Aside from that, we need some jQuery to move the background and assign a duration to the effect. This is shown below:
jQuery
$(document).ready(function(){
$('#wine li span').mouseover(function(){
$(this).stop().animate(
{backgroundPosition:"(0 0)"},
{duration:2000})
})
.mouseout(function(){
$(this).stop().animate(
{backgroundPosition:"(0 300px)"},
{duration:2000})
})
});
The jQuery here is quite straightforward, it just moves the background image of the 'span' element, the one which contains our moving 'fill' image up and down.
The clever bit in all of this is the usage of image transparency to give both a front and back to a realistic object, whereas traditionally and even with the advent of jQuery this would have been done with just two images.
As I've briefly touched on above, I will be developing this method to involve a y-axis transformation to give a more realistic 'top' to the moving component, perhaps add a feathered top to the moving image and possibly to remove the 'span' element from the source HTML and add it at runtime via jQuery in a similar method to the psuedo divs that many use in their jQuery navigation these days.
This is purely a proof of concept, and the potential of this mildly outside the box thinking lend itself to several other realistic transitions heavily based around transparency such as windows opening which previously, only technologies like flash have offered.