Thursday, January 7, 2010

Dynamic Text Highlighting with jQuery

I’ve got my hands dirty with jQuery once again, creating animated text line with dynamic highlighting of its letters. As usual I started by looking for existing plug-ins – didn’t find quite what I needed, so I wrote my own animation. It is possible that there are ones that I just missed, but thanks to jQuery my own animation ended up being pretty simple, which I want to illustrate here.

I was dynamically writing out letters and changing their font-weight CSS property to create the effect of highlighting. I think it worked out nicely. It even works on my iPhone 3G. You can see the page here. Below are a couple of notes on its source code:

It starts with displaying a semi-transparent banner by using jQuery animate function to change its left CSS property. The banner (id=”motto”) is clipped by a surrounding div (id=”mottoclip”), which creates the perception of it appearing out of nothing rather than simply sliding horizontally. With jQuery it is as simple as this:

$("#motto").animate(
{ left: "2px" },
{ duration: rolloverDuration, easing: "linear", complete: showMotto });

Once the banner is in place the showMotto() callback function sets up a recursive output of the letters. The recursion is implemented in writeText() function. It outputs the motto line of text one letter per recursion, setting timeout between them. In order to be able to “highlight” a letter, it needs to be placed in its own span. The letter becomes visible once its span is added to the parent container through jQuery append() method:

var characterSpan = "<span id='mt" + i + "'>" + character + "</span>";
container.append(characterSpan);

Then we construct a jQuery selector object for each character, so that we can easily animate it. Next, call a function animateLetter() where we first hide letter completely, then gradualy show it in bold (font-weight: 700), then return to normal (font-weight: 400):

function animateLetter(jChar, letterShowTimeout, letterResetTimeout)
{
jChar.hide();
jChar.css("display", "inline");
jChar.css("font-weight", 400);
jChar.show(letterShowTimeout, function() { jChar.css("font-weight", 700); });
setTimeout(function() { jChar.css("font-weight", 400); }, letterResetTimeout);
}

At this point we move on to writing out and animating the next letter, and so on.

Lastly there is an “artistic touch” on all this – the easing. Easing determines how an animation ends to create a pleasant visual effect. You’ve probably seen menu fly-outs that appear to oscillate slightly at the end of their path, or they simply slow down, etc. By the way one great example of this can be seen in jQuery Scrollable control.

In my case easing was implemented starting at 14th character of the motto text. From that point the timeout between displaying letters increased exponentially, and timeout between making each letter bold and resetting it back to normal – linearly with each iteration:

var letterShowTimeout = 60;
var letterResetTimeout = 90;
var easingStartLength = 14;

if ( i > easingStartLength )
{
var easing = Math.ceil((i - easingStartLength) / 3);
var easingSq = easing * easing;
letterShowTimeout += easingSq * letterShowTimeout;
letterResetTimeout += easing * letterResetTimeout;
}

If you think of the animation as of lighting up a string of text with a flashlight, the easing creates an effect of the light spot getting wider towards the end. And yes, all the constants and exponents are empirical. If you want to use something similar, you’ve got to experiment with numbers.

No comments:

Post a Comment