13.9.1. Building a Clock with Clips
In this chapter we learned how to create
movie clips with attachMovie( ) and how to set
movie clip properties with the dot operator. With these relatively
simple tools and a little help from the Date and
Color classes, we have everything we need to
make a clock with functional hour, minute, and second hands.
First, we'll make the face and hands of the clock with the
following steps (notice that we don't place the parts of our
clock on the main Stage -- our clock will be generated entirely
through ActionScript):
Start a new Flash movie.
Create a movie clip symbol named clockFace that
contains a 100-pixel-wide black circle shape.
Create a movie clip symbol named hand that
contains a 50-pixel-long, vertical red line.
Select the line in hand, then choose Window
Panels
Info.
Position the bottom of the line at the center of the clip by setting
the line's x-coordinate to
and its y-coordinate to -50.
Now we have to export our clockFace and
hand symbols so that instances of them can be
attached dynamically to our movie:
In the Library, select the clockFace clip, then
select Options
Linkage. The Symbol Linkage Properties dialog
box appears.
Select Export This Symbol.
In the Identifier box, type clockFace and then
click OK.
Repeat steps 1 through 3 to export the hand clip,
giving it the identifier hand.
The face and hands of our clock are complete and ready to be attached
to our movie. Now let's write the script that places the clock
assets on stage and positions them with each passing second:
Add the script shown in Example 13-4 to frame 1 of
Layer 1 of the main timeline.
Rename Layer 1 to scripts.
Skim Example 13-4 in its entirety first, then
we'll dissect it.
Example 13-4. An Analog Clock
// Create clock face and hands
attachMovie("clockFace", "clockFace", 0);
attachMovie("hand", "secondHand", 3);
attachMovie("hand", "minuteHand", 2);
attachMovie("hand", "hourHand", 1);
// Position and size the clock face
clockFace._x = 275;
clockFace._y = 200;
clockFace._height = 150;
clockFace._width = 150;
// Position, size, and color the clock hands
secondHand._x = clockFace._x;
secondHand._ y = clockFace._ y;
secondHand._height = clockFace._height / 2.2;
secondHandColor = new Color(secondHand);
secondHandColor.setRGB(0xFFFFFF);
minuteHand._x = clockFace._x;
minuteHand._ y = clockFace._ y;
minuteHand._height = clockFace._height / 2.5;
hourHand._x = clockFace._x;
hourHand._ y = clockFace._ y;
hourHand._height = clockFace._height / 3.5;
// Update the rotation of hands with each passing frame
function updateClock( ) {
var now = new Date( );
var dayPercent = (now.getHours( ) > 12 ?
now.getHours() - 12 : now.getHours( )) / 12;
var hourPercent = now.getMinutes( )/60;
var minutePercent = now.getSeconds( )/60;
hourHand._rotation = 360 * dayPercent + hourPercent * (360 / 24);
minuteHand._rotation = 360 * hourPercent;
secondHand._rotation = 360 * minutePercent;
}
That's a lot of code, so let's review it.
We attach the clockFace clip first and assign it a
depth of
(we want it to appear behind our clock's hands):
attachMovie("clockFace", "clockFace", 0);
Next we attach three instances of the hand symbol,
assigning them the names secondHand,
minuteHand, hourHand. Each hand
resides on its own layer in the programmatically generated clip stack
above the main timeline. The secondHand (depth 3)
sits on top of the minuteHand (depth 2), which
sits on top of the hourHand (depth 1):
attachMovie("hand", "secondHand", 3);
attachMovie("hand", "minuteHand", 2);
attachMovie("hand", "hourHand", 1);
At this point our code would place the clock in the top-left corner
of the Stage. Next, we move the clockFace clip to
the center of the Stage and make it larger using the
_height and _width properties:
clockFace._x = 275; // Set the horizontal location
clockFace._y = 200; // Set the vertical location
clockFace._height = 150; // Set the height
clockFace._width = 150; // Set the width
Then we move the secondHand clip onto the clock
and make it almost as long as the radius of the
clockFace clip:
// Place the secondHand on top of the clockFace
secondHand._X = clockFace._x;
secondHand._y = clockFace._y;
// Set the secondHand's size
secondHand._height = clockFace._height / 2.2;
Remember that the line in the hand symbol is red,
so all our hand instances thus far are red. To
make our secondHand clip stand out, we color it
white using the Color class. Note the use of the
hexadecimal color value 0xFFFFFF (see the Reference 20.22 in Part III, "Language Reference" for
more information on manipulating color):
// Create a new Color object to control secondHand
secondHandColor = new Color(secondHand);
// Assign secondHand the color white
secondHandColor.setRGB(0xFFFFFF);
Next we set the position and size of the
minuteHand and hourHand, just
as we did for the secondHand:
// Place the minuteHand on top of the clockFace
minuteHand._x = clockFace._x;
minuteHand._y = clockFace._y;
// Make the minuteHand shorter than the secondHand
minuteHand._height = clockFace._height / 2.5;
// Place the hourHand on top of the clockFace
hourHand._x = clockFace._x;
hourHand._y = clockFace._y;
// Make the hourHand the shortest of all
hourHand._height = clockFace._height / 3.5;
Now we have to set the rotation of our hands on the clock according
to the current time. However, we don't just want to set the
rotation once. We want to set it repetitively so that our clock
animates as time passes. Therefore, we put our rotation code in a
function called updateClock( ), which
we'll call repeatedly:
function updateClock( ) {
// Store the current time in now
var now = new Date( );
// getHours() works on a 24-hour clock. If the current hour is greater
// than 12, we subtract 12 to convert to a regular 12-hour clock.
var dayPercent = (now.getHours( ) > 12 ?
now.getHours() - 12 : now.getHours( )) / 12;
// Determine how many minutes of the current hour have passed, as a percentage
var hourPercent = now.getMinutes( )/60;
// Determine how many seconds of the current minute have passed, as a percentage
var minutePercent = now.getSeconds( )/60;
// Rotate the hands by the appropriate amount around the clock
hourHand._rotation = 360 * dayPercent + hourPercent * (360 / 24);
minuteHand._rotation = 360 * hourPercent;
secondHand._rotation = 360 * minutePercent;
}
The first task of updateClock( ) is to retrieve
and store the current time. This is done by creating an instance of
the Date class and placing it in the local
variable now. Next we determine, as a percentage,
how far around the clock each hand should be placed -- much like
determining where to slice a pie. The current hour always represents
some portion of 12, while the current minute and second always
represent some portion of 60. We assign the
_rotation of each hand based on those percentages.
For the hourHand, we reflect not only the percent
of the day but also the percent of the current hour.
Our clock is essentially finished. All that's left to do is
call the updateClock( ) function with each
passing frame. Here's how:
Add two keyframes to the scripts layer.
On frame 2, add the following code: updateClock(
);
On frame 3, add the following code: gotoAndPlay(2);
Test the movie and see if your clock works. If it doesn't,
compare it to the sample clock .fla file
provided at the online Code Depot or check your code against Example 13-4. Think of ways to expand on the clock
application: Can you convert the main timeline loop (between frames 2
and 3) to a clip event loop? Can you make the clock more portable by
turning it into a Smart Clip? How about dynamically adding minute and
hour markings on the clockFace?