Hack 2 Per-Pixel Text Effects 
Create advanced text effects and
transitions that operate on the per-pixel level.
The problem in simulating per-pixel effects in Flash is that
potential performance degradation limits how many fake pixels you
use. You have two ways to keep this number small: keep to small
images (as we did in the per-pixel transition effect hack [Hack #1]), or use the effect on
an image with lots of background pixels (which you can ignore to
reduce the number of fake pixels needed).
Although it's probably obvious in hindsight, it took
me ages to realize that text fits the "lots of
background pixels" criterion. A quick trawl on the
Web suggests that it really isn't obvious because
nobody else seems to be using this hack.
In this hack, we'll make the text appear to coalesce
from pixels spread out over the screen. Of course, you can implement
various effects using different calculations for the mask
pixels' positions.
The hack comes in two parts:
Converting the text block's shape into 1x1 squares
(i.e., our "fake pixels") Animating the fake pixels
Here are the steps:
Create a text field and enter some text. Press Ctrl-B (Windows) or -B (Mac) or choose
Modify Break Apart twice to turn the text field into a
primitive shape. With the text still selected, press F8, and convert it into a movie
clip symbol named text. Make sure the Export
for ActionScript checkbox is checked and specify the linkage
identifier as text. (Delete the clip instance
from the Stage, as we'll be adding it at runtime
from the Library with MovieClip.attachMovie( ).) For the effect to work, the movie clip's
registration point must be at the top left of the text. Enter Edit in
Place mode by double-clicking the movie clip; then to select all the
text choose Edit Select All and enter 0 for X and Y values
in the Properties panel, as shown in Figure 1-6.

You must turn your text into a primitive shape for this hack to work
using the Modify Break Apart command
(we'll see why later), which is not ideal because it
adds to the filesize. For a lot of text, it can bloat the filesize
considerably. One way around this is to include each letter in your
font as a separate clip containing a primitive shape and form them
into sentences at runtime. Although this sounds like a lot of
additional bytes to add to your SWF, remember that Flash effectively
does the same thing when you save font outlines to your SWF, which
you have to do whenever you want to treat font characters as graphic
elements.
You also need to create a second movie clip with linkage identifier
dot. The dot clip should
consist of a 1 1 rectangle, with X and Y positions both set to 0 as
shown in Figure 1-7 (use the Properties panel to
set these because the dot will be too small to see).

This code replicates the "zoom in from the sides
with blur" effect, but this time the text
really does blur (the effect is usually
simulated with alpha), as shown in Figure 1-8,
because we are splitting the text into pixels as part of the effect.

function mover( ) {
this._x -= (this._x - this.x) / 4;
this._y -= (this._y - this.y) / 4;
}
function lastMover( ) {
this._x -= (this._x - this.x) / 4;
this._y -= (this._y - this.y) / 4;
if ((this._x - this.x) < 0.1) {
dotHolder.removeMovieClip( );
textClip._visible = true;
}
}
// Place the text on the Stage and hide it
textClip = this.attachMovie("text", "textClip", 0);
textClip._x = 200;
textClip._y = 100;
textClip._visible = false;
// Initialize variables, including height and width
var dots = 1;
var distance = 10000;
var stopDot = true;
var height = textClip._y + textClip._height;
var width = textClip._x + textClip._width;
// Create a dot clip for every pixel in the text
var dotHolder = this.createEmptyMovieClip("holder", 1);
for (var j = textClip._y; j < height; j++) {
for (var i = textClip._x; i < width; i++) {
if (textClip.hitTest(i, j, true)) {
var clip = dotHolder.attachMovie("dot", "dot" + dots, dots);
if (stopDot) {
clip._x = distance;
clip.onEnterFrame = lastMover;
stopDot = false;
} else {
clip._x = Math.random( ) * distance - distance/2;
clip.onEnterFrame = mover;
}
// Store the position that the dot clip has
// to get to (clip.x, clip.y) and move it off screen
clip.x = i;
clip.y = j;
clip._y = j;
dots++;
}
}
}
Ignoring the mover( ) and lastMover(
) function definitions for a moment, the remaining code
places the text on the Stage and hides it. The code then initializes
several variables, including those that define the height and width
of our text.
The subsequent for loop uses
MovieClip.hitTest( ) to find all nonempty pixels in the
text and create a dot movie clip corresponding to
each. Each of these dots is given an onEnterFrame(
) handler to animate the overall effect. (Instead, we
could use setInterval( ) to animate the effect
[Hack #1].)
Two hacks are at work in this loop code.
The first hack, using hitTest( ), is the reason
we had to break apart our text. The hitTest( )
method always returns false when used with a
dynamic text field (in which case it treats all pixels as empty).
The second hack is the way we check that all pixels are in their
final positions. Most of our pixels are placed randomly on the screen
and controlled by the event handler mover(
). The first pixel, however, is placed
furthest away and also given a slightly more complicated event
handler, lastMover( ). This event stops the
effect when the associated pixel has moved to its final position, by
which time the others will also have reached their final positions
(given that they all have less distance to travel).
 |
Although a bit of a kludge, this hack is far more
performance-friendly than forcing each pixel to perform a similar
check.
|
|
Final Thoughts
Although Flash text effects are all over the Web, I
don't know of any that use per-pixel transitions.
The cool thing about using our fake pixels is that you can use any
other particle effect (such as the snow, waterfall, or star field
effects [Hack #33] ) for the pixel
movement routine.
|