Wednesday, December 22, 2010

Animated scrolling background with parallax using jQuery

I wanted to distinguish the author comments on my blog in an interesting way. Here's what I came up with:


Click the image to see it live

Notice in the live view that there is a parallax effect: some of the clouds appear to float by closer than others. This is accomplished using two images with one on top of the other. The images used are these:
Background:
Transparent overlay:

Implementation

Two css classes are used, one for each image:
.byAuthor
{
color: Black;
background-image: url("http://lh4.ggpht.com/abbrev_path/sky.png");
padding: 5px;
}

.byAuthorOverlay
{
background-image: url("http://lh4.ggpht.com/abbrev_path/sky2.png");
}

Eventually our comments will take the form of two nested divs, each given one of the classes defined above with the overlay on top. For example:
<div class="byAuthor">
<div class="byAuthorOverlay">
Here is the text of the comment
</div>
</div>

Next comes the javascript. The setInterval() method is used to call a function which changes the Y offset of the background image. This is done twice: once for each image.
function scrollBackground(options) {
options.step = options.step || 1; //step property defaults to 1
options.top = options.top === undefined || Math.abs(options.top) >= options.bgImgHeight ? 0 : options.top - options.step;
options.$elements.css("background-position", "0 " + options.top + "px");
}

var mainBg = { speed: 30, bgImgHeight: 400 };
setInterval(function () { scrollBackground(mainBg); }, mainBg.speed);

var overlayBg = { speed: 50, bgImgHeight: 400 };
setInterval(function () { scrollBackground(overlayBg); }, overlayBg.speed);

scrollBackground() takes an object named "options" as an argument. Here is the definition of this object:
options = {
delta: 1, //Y delta - number of pixels by which to change the background-position each time
speed: 30, //time interval between animation steps (milliseconds)(lower is faster)
bgImgHeight: 400px, //height of the image being scrolled
$elements: $(".byAuthor") //a jquery set of elements to apply css changes to
}

setInterval() causes scrollBackground() to be called every X milliseconds. scrollBackground() calculates a new Y value for the background image and applies it. Notice that the "speed" values for each of the images is different. This causes the overlay image to scroll a little faster than the background image providing the parallax effect.

Applying to blogger

Getting this to work on blogger requires understanding of jQuery and the DOM. Because templates differ, you'll need to examine how blogger displays your comments, taking note of the DOM elements surrounding them. In my case, the DOM looks like this (trimmed for brevity):
<dt class="comment-author blog-author">Joel said... </dt>
<dd class="comment-body">
<p>
Comment Text
</p>
</dd>

I want to enclose the comment text within the two nested divs mentioned above. This is simple using jQuery:
    $(".blog-author").next().find("p").wrap('<div class="byAuthorOverlay" />');
$(".byAuthorOverlay").wrap('<div class="byAuthor" />');

That results in the following DOM layout:
<dt class="comment-author blog-author">Joel said... </dt>
<dd class="comment-body">
<div class="byAuthor" >
<div class="byAuthorOverlay" >
<p>
Comment Text
</p>
</div>
</div>
</dd>

And now, with both setInterval() functions executing at the prescribed intervals, the background images for the new divs appear to scroll upward.

No comments:

Post a Comment