I am most pleased to be able to show you how to create an analog clock in Flash using ActionScript only.

You won’t be touching any tools whatsoever. This is just about programming in Flash. Also, there is no timeline animation involved and no layers. And, this works in Flash MX, Flash MX 2004 and Flash 8.

Just look at the flash example below to see what is possible with actionscripting only.

That’s right, even the shine on the left side of the clock frame was made with actionscript, just like the lines marking the hours and the minutes, and the clock hands too.

In this tutorial, you will make a simpler clock (but completely functional like the one above). At the end, I will briefly explain you how the stylish details were made and you will have the source for both clocks available for download.

### Setting up the base movie clip for the clock

1 Open a new Flash document. Save it immediately so that you can just press

**CTRL+S**later.3 Select the first keyframe. This will be the only one, too – remember, there is no timeline animation here.

Select

**Window > Actions**to open up the Actions panel for the frame you just selected. If you are new to actionscripting, know that all actions placed on this (first) keyframe will be executed immediately upon loading of this movie.4 Enter in the following code:

this.createEmptyMovieClip("clock", 3);

clock._x = 150;

clock._y = 150;

clock._x = 150;

clock._y = 150;

The above piece of code creates a new movie clip out of nothing. The keyword

`this`

designates the object this piece of code is placed upon. As in this particular case the code is placed on the main timeline, the keyword`this`

denotes the main timeline – this means the flash movie itself.The

`createEmptyMovieClip`

command creates a new movie clip, obviously. There are two parameters between the parentheses which must be included if everything is to function as intended.The first one is the instance name –

`"clock"`

. That means the name of the movie clip you are creating. You need to specify it, because you wouldn’t be able to manipulate the movie clip later if it has no name by which you can reference it. And, you have to put the name between quotation marks, otherwise flash will think that it is a variable and not an instance name you are talking about.The second parameter is the depth of the movie clip. Think of that as a layer created with actionscript. The bigger the number, the higher the stack position of the movie clip. It means that the movie clip with, say, a depth of 50, will be in front of (on the screen) a movie clip with a lesser depth, like 40 or 6, or 11, etc. I put the depth 3 arbitrarily.

When creating a movie clip with the

`createEmptyMovieClip`

method, always give it a unique depth parameter. If you were to create a new movie clip after that, with the same depth as the previous one, that new movie clip would erase completely the previous one. Also, if any of the two parameters are missing (instance name or depth, or both), the creation of the movie clip will fail completely.The next two lines are positioning the newly made movie clip on the stage. This is necessary because when you create a new movie clip using the

`createEmptyMovieClip`

method, it is by default positioned in the upper left corner of the stage, with the coordinates (0,0).So the

`clock._x = 150;`

line positions the *clock*movie clip 150 pixels to the right from the left stage edge. The second one positions it 150 pixels down from the top edge of stage (the positive Y coordinates are below the top stage edge in flash). There is no`this`

keyword at the beginning of the two lines because the movie clip was created on the main, or root, timeline in the first line of code, so you just write its name (*clock*) and flash will look for it on the root timeline.If you test your movie at this point, you won’t see anything, but the movie clip is created and positioned on stage. If you are still not convinced then select

**Debug > List Objects**while in the test movie mode. Flash will nicely list the movie clip.### Making the circle – the clock’s frame

5 Add this actionscript code after the existing one:

clock.createEmptyMovieClip("circle", 1);

clock.circle.lineStyle(4, 0x000066, 100);

clock.circle.moveTo(100, 0);

circleRadius = 100;

for (a=0; a<361; a++) {

radAngle = a*Math.PI/180;

xCoord = Math.cos(radAngle)*circleRadius;

yCoord = Math.sin(radAngle)*circleRadius;

clock.circle.lineTo(xCoord, yCoord);

}

clock.circle.lineStyle(4, 0x000066, 100);

clock.circle.moveTo(100, 0);

circleRadius = 100;

for (a=0; a<361; a++) {

radAngle = a*Math.PI/180;

xCoord = Math.cos(radAngle)*circleRadius;

yCoord = Math.sin(radAngle)*circleRadius;

clock.circle.lineTo(xCoord, yCoord);

}

Test your movie. You should have a circle drawn by flash like the one below showing up.

First, you created a new movie clip using the

`createEmptyMovieClip`

command. This new movie clip is created inside the *clock*movie clip. Now why do that instead of repeating the same thing as you did in the beginning, using the`this`

keyword?Because if you move the original, the base movie clip

*clock*, to another position on the stage (let’s say you changed the layout of your flash site), the newly created*circle*would stay on the old position.But, when you create the

*circle*movie clip**the***inside**clock*movie clip by using the lineclock.createEmptyMovieClip("circle", 1);

this problem is solved. Now, if you decide to move the

*clock*, the*circle*will follow it. In that way, you have all things situated inside the*clock*movie clip.The line

clock.circle.lineStyle(4, 0x000066, 100);

sets the style of the line before the drawing starts. You always have to do this. If you’re not familiar with actionscript drawing commands, I suggest you go and read the basic drawing with actionscript tutorial.

The line

`clock.circle.moveTo(100, 0);`

moves the *circle*movie clip’s starting position for drawing. Note that the starting position of drawing for a movie clip is its registration point, which is the zero point of its own coordinate system. The stage is no longer used as a reference.Why did you have to move the starting position for drawing? I will explain it in a moment.

The line

`circleRadius = 100;`

is where the `circleRadius`

variable is defined and its value is 100. This value defines the radius of your clock’s frame.Now comes a

`for`

loop that actually draws the circular frame for your clock.for (a=0; a<361; a++) {

radAngle = a*Math.PI/180;

xCoord = Math.cos(radAngle)*circleRadius;

yCoord = Math.sin(radAngle)*circleRadius;

clock.circle.lineTo(xCoord, yCoord);

}

radAngle = a*Math.PI/180;

xCoord = Math.cos(radAngle)*circleRadius;

yCoord = Math.sin(radAngle)*circleRadius;

clock.circle.lineTo(xCoord, yCoord);

}

This loop repeats 360 times. That’s because there are 360 degrees in a circle and this piece of code is drawing the circle from point to point.

The first line inside the loop defines the

`radAngle`

variable. This variable’s purpose is to store the angle for calculating the drawing points of the circle, *. This is necessary since the next two lines of code use flash’s built-in math trigonometric functions which work with***in radians***instead of***radians***values.***degree**So the expression

`a*Math.PI/180`

is a simple mathematical formula used to convert degree values into radians. Here is a little basic math reminder:This angle increases every time as the loop increments. It stops when it comes full circle (pardon the pun) from 0 to 360 degrees.

Now comes the interesting part in which I will explain to you how the trigonometrical functions are used to draw the circle.

### The actionscript trigonometric functions used to find the coordinates for drawing explained

The X coordinate is found with this piece of actionscript:

xCoord = Math.cos(radAngle)*circleRadius;

It is stored in a variable called

`xCoord`

.What does the right side of the expression do? I’ll explain a little bit of high school math now. Wait. Wait! Don’t run away It IS easy. And it is fun once you see the possibilities and creativity it offers you. I pretty much shunned away all the math after my studies, but once I lay my hands on Flash and saw that I had to implement it if I wanted to do some advanced actionscripting, I quickly remembered and looked up what I needed. So will you! Continue and you’ll see how interesting and cool math is!

So, you need to know the coordinates of every point on the circle to draw it. How do you find a point on a circle? Simple, with two pieces of data you already have. The angle and the radius. Look at the diagram below.

I took an angle of 30 degrees arbitrarily for the purpose of explaining this calculation. So, you’re looking for the X and Y coordinates of the T point on the circle.

The X coordinate of the

**point equals to the distance***T***on the diagram, which is the distance from the starting point***a**to the***(0,0)***point on the diagram. How to find the value of this distance? With trigonometry.***x**The triangle formed with the sides

*,***a***and***b***in the diagram is a***c***. It means there is a right angle (90°) inside it. It is found between the sides***right triangle***and***a***. There are some great trigonometrical functions that can be used with this kind of triangle.***b**The

*of an angle (the angle is marked with the greek letter lambda –***cosine***) is the ratio of the length of the triangle side adjacent to the angle (***?***in the diagram) to the length of the hypotenuse (the hypotenuse being the side opposite the right angle,***a***in the diagram). So, the formula goes like this:***c**Written in a single line it goes like this:

cos ? = adjacent side / hypotenuse

If you apply the distances from the diagram to the formula, it would turn out this way:

cos ? = a / c

In your actionscript code, the angle

*is defined in the variable***?**`radAngle`

and the hypotenuse *is the radius of the circle, defined in the variable***c**`circleRadius`

. What is left is the adjacent side *, which is the X coordinate of the T point you’re looking for. That coordinate is named***a**`xCoord`

in your code. So, the formula turned into actionscript looks like this:Math.cos(radAngle) = xCoord / circleRadius;

But you’re looking for the T point’s X coordinate, right? So, the final line of code you need looks like this:

xCoord = Math.cos(radAngle) * circleRadius;

And that’s it! The similar explanation goes for the Y coordinate. You’re smart so just look at the diagram and apply the same logic to discover the explanation for finding the Y coordinate value.

So after finding both coordinates for each point (360 points in total because that’s the number of iterations the loop is going through),

xCoord = Math.cos(radAngle)*circleRadius;

yCoord = Math.sin(radAngle)*circleRadius;

yCoord = Math.sin(radAngle)*circleRadius;

flash finally draws the line by executing the following code:

clock.circle.lineTo(xCoord, yCoord);

OK, the method

`lineTo`

draws the line to the coordinates specified within the parentheses. But where does the line start? Where is it drawn from?This was defined in the line

clock.circle.moveTo(100, 0);

before the loop. After that first line is drawn, the loop passes to the next iteration and draws from the last point (as drawing in flash is set up to do, if there was no

`moveTo`

command in between) to the next one, which is again calculated with the aid of the cosine and sine functions.But, you ask again, why did I used the

`moveTo`

command to move to the point (100, 0) and not some other point?Because the calculation for the first angle is for the 0 degree angle, which is situated at three o’clock in flash. That’s why you need to move the starting point for drawing here, so that it continues naturally following the circle.

Look at this diagram explaining it.

I put a lot of distance between the three marked points to make the diagram more easy to read. In reality, these points are right next to one another.

So, the first point (100, 0) is right on the horizontal axis of the circle. This is where the drawing will begin, this was done with the

`moveTo`

command explained above.Soon after this line of code, the loop begins and the first point on the circle (T

_{1}) is calculated. A line is drawn from (100, 0) to (T_{1}) with the`lineTo`

command which follows the calculation of the point. The loop goes through the next iteration and calculates the coordinates for the second point (T_{2}). A line is drawn from the previous point (T_{1}) to this one (T_{2}).And this goes on until the loop ends, that is, after 358 more iterations. So, I suppose you got the trick by now: the circle is in fact a 360-sided polygon! But the sides of the polygon are so close that it look like a circle. Cool, no? Absolutely cool!

### Creating the markings for the hours and the minutes

The circle with the main concept of advanced drawing with actionscript being thoroughly explained, it’s time for you to create the markings for the hours and the minutes.

The method used is the same, with some differences and catches.

6 Type in the following lines right after all the code you entered so far:

clock.circle.lineStyle(3, 0x000000, 100);

clock.circle.moveTo(100, 0);

circleRadius = 100;

smallerCircleRadius = 90;

for (h=0; h<12; h++) {

hourAngle = h*30;

radHourAngle = hourAngle*Math.PI/180;

xCoord1 = Math.cos(radHourAngle)*circleRadius;

yCoord1 = Math.sin(radHourAngle)*circleRadius;

xCoord2 = Math.cos(radHourAngle)*smallerCircleRadius;

yCoord2 = Math.sin(radHourAngle)*smallerCircleRadius;

clock.circle.moveTo(xCoord1, yCoord1);

clock.circle.lineTo(xCoord2, yCoord2);

}

clock.circle.moveTo(100, 0);

circleRadius = 100;

smallerCircleRadius = 90;

for (h=0; h<12; h++) {

hourAngle = h*30;

radHourAngle = hourAngle*Math.PI/180;

xCoord1 = Math.cos(radHourAngle)*circleRadius;

yCoord1 = Math.sin(radHourAngle)*circleRadius;

xCoord2 = Math.cos(radHourAngle)*smallerCircleRadius;

yCoord2 = Math.sin(radHourAngle)*smallerCircleRadius;

clock.circle.moveTo(xCoord1, yCoord1);

clock.circle.lineTo(xCoord2, yCoord2);

}

Test your movie. The markings for the hours will appear. Let me quickly explain you how this is done.

The first line changes the style of the drawing line, so that it appears thicker. You can make it any color and thickness that you want, but the important thing is to make it more prominent than the minutes’ markings. Remember, the time must be easily redable from the clock. Be nice to your users!

There is the

`circleRadius`

variable again, which is listed here for easier comprehension. There is also a new addition, `smallerCircleRadius`

. These two circle radiuses will make it possible to draw a line from the outer circle to the inner circle.The loop has only 12 iterations now, which makes sense because this is the number of the hours’ markings on a standard analog clock.

Inside the loop, the first line of code defines the angle at which the calculations are made. This angle is the loop’s iteration multiplied by 30.

I hear you asking: why?

Because a full circle has 360 degrees, and there are 12 hours on an analog clock. So by multiplying each iteration number (0, 1, 2… till 11) with 30, you obtain the angles at which the markings for the hours must be positioned.

After the conversion of the angle from degrees to radians (the same formula as in the previous step), there are two pairs of coordinates calculated, followed by a

`moveTo`

command that defines a new starting drawing point for each iteration, and then drawing with the `lineTo`

command.xCoord1 = Math.cos(radHourAngle)*circleRadius;

yCoord1 = Math.sin(radHourAngle)*circleRadius;

xCoord2 = Math.cos(radHourAngle)*smallerCircleRadius;

yCoord2 = Math.sin(radHourAngle)*smallerCircleRadius;

clock.circle.moveTo(xCoord1, yCoord1);

clock.circle.lineTo(xCoord2, yCoord2);

yCoord1 = Math.sin(radHourAngle)*circleRadius;

xCoord2 = Math.cos(radHourAngle)*smallerCircleRadius;

yCoord2 = Math.sin(radHourAngle)*smallerCircleRadius;

clock.circle.moveTo(xCoord1, yCoord1);

clock.circle.lineTo(xCoord2, yCoord2);

I put the points on another part of the circle, but this is applicable on all of it.

After placing the drawing position on B

_{1}, it draws the line to S_{1}, which is found on the inner, smaller circle. The lines are drawn perfectly pointing at the center of the circle because the angle calculated is the same for the small and the big circle in each iteration. Then flash moves the starting drawing position again, this time to B_{2}, and draws the line to S_{2}.It is easy once the main concept is grasped, isn’t it?

You should create the markings for the minutes now, using a thinner line this time.

7 Place the following actionscript at the end of your current code:

clock.circle.lineStyle(1, 0x000000, 100);

clock.circle.moveTo(100, 0);

circleRadius = 99;

smallerCircleRadius = 91;

for (m=0; m<60; m++) {

minuteAngle = m*6;

radMinuteAngle = minuteAngle*Math.PI/180;

xCoord1 = Math.cos(radMinuteAngle)*circleRadius;

yCoord1 = Math.sin(radMinuteAngle)*circleRadius;

xCoord2 = Math.cos(radMinuteAngle)*smallerCircleRadius;

yCoord2 = Math.sin(radMinuteAngle)*smallerCircleRadius;

clock.circle.moveTo(xCoord1, yCoord1);

clock.circle.lineTo(xCoord2, yCoord2);

}

clock.circle.moveTo(100, 0);

circleRadius = 99;

smallerCircleRadius = 91;

for (m=0; m<60; m++) {

minuteAngle = m*6;

radMinuteAngle = minuteAngle*Math.PI/180;

xCoord1 = Math.cos(radMinuteAngle)*circleRadius;

yCoord1 = Math.sin(radMinuteAngle)*circleRadius;

xCoord2 = Math.cos(radMinuteAngle)*smallerCircleRadius;

yCoord2 = Math.sin(radMinuteAngle)*smallerCircleRadius;

clock.circle.moveTo(xCoord1, yCoord1);

clock.circle.lineTo(xCoord2, yCoord2);

}

The only thing that needs to be noted at this step is that I changed the radiuses for both circles, so that the minutes’ markings are a little bit shorter than the hours’ markings.

This loop goes through 60 iterations because there are 60 minutes in an hour. Inside the loop, this number is multiplied by 6, to get the right angle for each minute’s marking. Similar calculation as before: 360 degrees in a circle, 60 minutes in an hour. 360 divided by 60 yields 6. The rest (moving and drawing) is as same as for the hours’ markings.

Test your movie. Cool! You should have the same result as in the image on the left (the screenshot on the image is scaled down).

### Drawing the seconds, minutes and hours hands

You’ll now proceed to make the clock’s hands. This is a little bit simpler than circle drawing with actionscript

8 Add the following code to the existing one:

clock.createEmptyMovieClip("hoursHand", 20);

clock.hoursHand.lineStyle(6, 0x000000, 100);

clock.hoursHand.moveTo(0, 0);

clock.hoursHand.lineTo(0, -50);

clock.hoursHand.lineStyle(6, 0x000000, 100);

clock.hoursHand.moveTo(0, 0);

clock.hoursHand.lineTo(0, -50);

This is simple, you only need to be careful about some details. At first, the movie clip is created. Its depth is set above the

*circle*movie clip’s hand, because you want all the hands to be above the circle and other drawings.A thicker line is chosen for drawing style. Next, the beginning of the drawing is moved to (0, 0). This is very important. This is the registration point of the hours hand movie clip and it is around this point that the hand will rotate.

The

`lineTo`

command draws the hand.9 Add the code that follows:

clock.createEmptyMovieClip("minutesHand", 30);

clock.minutesHand.lineStyle(5, 0x000000, 100);

clock.minutesHand.moveTo(0, 0);

clock.minutesHand.lineTo(0, -81);

clock.minutesHand.lineStyle(5, 0x000000, 100);

clock.minutesHand.moveTo(0, 0);

clock.minutesHand.lineTo(0, -81);

clock.createEmptyMovieClip("secondsHand", 40);

clock.secondsHand.lineStyle(0, 0xFF0000, 100);

clock.secondsHand.moveTo(0, 0);

clock.secondsHand.lineTo(0, -90);

clock.secondsHand.lineStyle(0, 0xFF0000, 100);

clock.secondsHand.moveTo(0, 0);

clock.secondsHand.lineTo(0, -90);

This is the code to create the minutes and the seconds hand.

Note that each hand movie clip’s depth is bigger than the previous one. In that way, the clock hands are stacked one on top of another. I chose the depths 20, 30 and 40. It could have been 11, 12 and 13 or any other three numbers. But it is always wise to let some “space” between the depths. You never know, you might decide to add something in between later and then you’ll be glad you did this.

Test the movie and you’ll see the hands stacked one on top of another.

### Setting the clock in motion

Yes! Finally, you get to start the clock! Just a liiiiittle bit more!

10 Enter the final piece of code:

clock.onEnterFrame = function () {

clockDate = new Date();

seconds = clockDate.getSeconds();

this.secondsHand._rotation = seconds * 6;

minutes = clockDate.getMinutes();

this.minutesHand._rotation = minutes * 6;

hours = clockDate.getHours();

this.hoursHand._rotation = (hours * 30) + (minutes/2);

}

clockDate = new Date();

seconds = clockDate.getSeconds();

this.secondsHand._rotation = seconds * 6;

minutes = clockDate.getMinutes();

this.minutesHand._rotation = minutes * 6;

hours = clockDate.getHours();

this.hoursHand._rotation = (hours * 30) + (minutes/2);

}

Test your movie. The seconds hand should tick! This is the best way to check if your clock is working.

This portion of code creates a function assigned to the

*circle*movie clip’s`onEnterFrame`

event. This means that the function will get executed as many times per second as there are frames per second set in your movie’s speed (fps option in your document’s properties).Inside the function, there is a new date object created. This is obligatory if you want flash to tell you what time or date it is. The lines

seconds = clockDate.getSeconds();

minutes = clockDate.getMinutes();

hours = clockDate.getHours();

minutes = clockDate.getMinutes();

hours = clockDate.getHours();

create variables in which the information on current seconds, minutes and hours are stored.

A little bit more interesting are code lines that govern the rotation of the clock’s hands.

this.secondsHand._rotation = seconds * 6;

this.minutesHand._rotation = minutes * 6;

this.hoursHand._rotation = (hours * 30) + (minutes/2);

this.minutesHand._rotation = minutes * 6;

this.hoursHand._rotation = (hours * 30) + (minutes/2);

The

`this`

keyword points to the *clock*movie clip, since it is situated in a function which is assigned to this same movie clip’s`onEnterFrame`

event. So, `this.secondsHand`

points to the movie clip *secondsHand*which is placed inside the*clock*movie clip. Just simple actionscript paths.Now, the

`_rotation`

property of these movie clips is what is found on the right side of these code lines. The`_rotation`

property value is expressed in degrees.Why are the minutes and seconds multiplied by 6?

For example, let’s say that flash just read the time which said it is exactly 15 seconds now. This means the

*secondsHand*movie clip should be pointing at 3 o’clock. This is 90 degrees in relation to its starting position of 0 degrees. That’s why you have to multiply by 6. This is what happens at runtime:this.secondsHand._rotation = seconds * 6;

this.secondsHand._rotation = 15 * 6;

this.secondsHand._rotation = 90;

this.secondsHand._rotation = 15 * 6;

this.secondsHand._rotation = 90;

The initial value for the

`_rotation`

property of any movie clip is 0 degrees, which is pointing straight upwards, in contrast with the sine and cosine values discussed in previous steps of this tutorial, which point at the right side, horizontally. OK? Don’t confuse these two values, who have nothing to do with one another.The same is with the clock’s minutes hand.

But there is a difference with the hours hand. Its code says

this.hoursHand._rotation = (hours * 30) + (minutes/2);

If you just put in

this.hoursHand._rotation = hours * 30;

it would work, but in a misleading way. The result of the equation on the right side of the expression would be the following: let’s say it’s 11:50 now. 11 multiplied by 30 would yield 330, which means 330 degrees, which points right to 11 o’clock. This is ok, right?

No. It is not good! The hours hand would point

*at 11 o’clock, while it is 11:50. This means the hours hand should be pointing almost at 12 o’clock at this time. Just look at the image below to see what I mean.***straight**Imagine you have to be somewhere at noon. This particular clock makes you think it’s almost 11 o’clock, instead of 12. Now you would miss that great movie, blind date or work interview (hopefully in the web design field). OK. How to correct this?

So, when it’s, let’s say, 11:30 (I’m not using 11:50 because 11:30 is easier to understand), the hours hand should be positioned right between 11 and 12 hour markings. So that’s why you add the minutes divided in half.

Imagine it is 11:30. The calculation would go like this:

this.hoursHand._rotation = (hours * 30) + (minutes/2);

this.hoursHand._rotation = (11 * 30) + (30/2);

this.hoursHand._rotation = 330 + 15;

this.hoursHand._rotation = 345;

this.hoursHand._rotation = (11 * 30) + (30/2);

this.hoursHand._rotation = 330 + 15;

this.hoursHand._rotation = 345;

That’s it – with this addition you get just the small increment you need to make the hours hand point to the right place.

You just finished the actionscript clock! Whoaaaa! Cool!

### The advantages of the actionscript-only clock

Just so that you know, the SWF generated from this flash document has a filesize of only 760 bytes!!! Do you realize what this means?

This means you can place this clock in an intro, preloader or in a banner! And it will load instantly, even on slower connections! Now that is radical! With this clock, you rule. Your site rules. Your client’s site rules.

And, what’s completely cool, this is written in ActionScript 1.0 and compatible with flash player 6 and above. So be sure to set the ActionScript version to 1.0 and the Flash player version to 6.0 in the Publish settings dialog if you are working in Flash 8 or Flash MX 2004.

You can also change the line thickness, colors and alpha of all the elements of the clock with just a few keystrokes. No re-editing or re-drawing. Just change the code! This lesson’s source files (both the simple clock and the one with the shining frame) can be downloaded below.

You want to be even more cool? Make the shine on the clock as you’ve seen it at the beginning of this tutorial. What’s the catch with the actionscript shine? It is using the same routine as the one used for generating the circle and the hours and the minutes markings. You just have to make smaller the range of the loop for this effect and put in the code that changes the alpha of the thick white line that is drawn. The line is fading at both ends, creating the shining effect. Voila!

## No comments:

## Post a Comment