1. Code
  2. JavaScript

Build a Custom Timer and Progress Meter in AS3

Scroll to top
17 min read

During this tutorial I will demonstrate how to make a custom timer which supports counting up or down to a specified amount of time.


Final Result Preview

In the demo below you will see the time counting down from 1:00, a progress bar that tracks the progress of the timer and a cancel button.

Once the countdown from the 1:00 is finished, or you press the cancel button, a Movie Clip slides in from the right. This Movie Clip lets you enter a desired time, and determines whether you have the time counting up or down. A progress bar will then be attached and will track the progress of the time. Once the time completes, or you press the cancel button, you will be able to enter a new time.


Step 1: Coding the Custom Timer Class

Here we will write the custom timer class that will drive our main movie.

Go to File > New and Choose Actionscript 3.0 Class. Save this file as "CountTimer.as".

Flash AS3 countdown timer stopwatch

Step 2: Import Classes

Here we open the package and import the classes that we will need to write this class.

Add the following to the "CountTimer.as"

1
2
3
package 
4
{
5
	//Needed for the Timer

6
	import flash.utils.Timer;
7
	import flash.events.TimerEvent;
8
	//We will update this TextField with the time

9
	import flash.text.TextField;

Step 3: Variables and Constructor Function

Here we will declare the variables the class will need, and code the constructor function.

Add the following to the "CountTimer.as".

1
2
public class CountTimer extends Timer
3
{
4
	//The textfield where the updated time goes

5
	private var targetText:TextField;
6
	//The direction of the timer i.e "up" or "down"

7
	private var direction:String;
8
	//How many minutes the timer has

9
	private var minutes:int;
10
	//How many seconds the timer has

11
	private var seconds:int;
12
	//Used in our calculation to update the timer

13
	private var totalSeconds:int;
14
	//The total amount of time = (Minutes+Seconds)

15
	private var timeTotal;
16
	//How much of the time has Passed

17
	private var timeLoaded = 0;
18
	//Set to true to test the timer

19
	private var test:Boolean = false;
20
	
21
	public function CountTimer(min:int,sec:int,dir:String,targetTextField:TextField=null)
22
	{
23
		minutes = int(min * 60);
24
		seconds = int(sec);
25
		timeTotal = minutes + seconds;
26
		super(1000,timeTotal);
27
		if (dir == "down")
28
		{
29
			totalSeconds = minutes + seconds;
30
		}
31
		else
32
		{
33
			totalSeconds = 0;
34
		}
35
		if (targetTextField != null)
36
		{
37
			targetText = targetTextField;
38
		}
39
		direction = dir;
40
	}

Here we declared some variables we need for our class.

The Constructor Function takes four parameters; they are as follows:

  • min: An integer value that represents how many minutes you wish the timer to have.
  • sec: An integer value that represents how many seconds you wish the timer to have.
  • dir: A string representing the direction of the counter can be one of the following: "up" or "down".
  • targetTextField: A TextField that will be used to show the updated time (This is optional).

Inside the constructor function we set the minutes variable equal to the specified value of min * 60 (since 1 minute is equal to 60 seconds).

We then set the seconds variable equal to the sec.

Next we set the timeTotal variable equal to minutes + seconds.

Then we call super() -- which run the code from the constructor function of the Timer class -- pass in 1000 milliseconds, and the timeTotal variable. By using 1000 milliseconds we tell the timer to tick one time each second, and by passing in timeTotal we tell the timer how many times to fire.

We next check whether the dir parameter is equal to "up" or "down" and set the totalSeconds variable accordingly.The total seconds will be used in our timeHandler() function. We will increment or decrement this by 1 each timer the timer fires off.

Then we check whether or not the user has passed in a TextField to the constructor and set the targetText variable if they did; this will be used to display the time.

Finally we set the direction variable to the direction the user passed in.


Step 4: Coding the start() Function

Here we code the start() function for our timer.

Add the following the the to the "CountTimer.as".

1
2
override public function start():void
3
{
4
	super.start();
5
	addEventListener(TimerEvent.TIMER, timerHandler);
6
}

Because we extended Timer we are overriding the Timer's existing start() method. Here we simply call super.start() (which runs the code from the Timer class's start() method) and add an EventListener to detect when the timer ticks.


Step 5: Coding the timerHandler Function

Here we code our timerHandler() function. This is where we update our time and display it. This function is called once every second.

Add the following to the CountTimer class.

1
2
private function timerHandler(e:TimerEvent):void
3
{
4
	//Update our time Loaded variable

5
	timeLoaded +=  1;
6
7
	if (direction == "up")
8
	{
9
		//totalSeconds is = 0, to start with. We add 1 to it.

10
		totalSeconds++;
11
	}
12
	else
13
	{
14
		//totalSeconds = theNumber of seconds by adding min and sec; we subtract 1 from it

15
		totalSeconds--;
16
	}
17
18
	//How may seconds there are left.

19
	seconds = totalSeconds % 60;
20
	//How many minutes are left

21
	minutes = Math.floor(totalSeconds / 60);
22
	//The minutes and seconds to display in the TextField.

23
	var minutesDisplay:String = (minutes < 10) ? "0" + minutes.toString() : minutes.toString();
24
	var secondsDisplay:String = (seconds < 10) ? "0" + seconds.toString(): seconds.toString();
25
	if (targetText != null)
26
	{
27
		targetText.text = minutesDisplay + ":" + secondsDisplay;
28
	}
29
	if (test=true)
30
	{
31
		trace(minutesDisplay + ":" + secondsDisplay);	
32
	}
33
}

Inside this function we update our timeLoaded variable, which is used to track the progress of how much time has passed.

Next we check whether direction is equal to "up" or "down" and adjust our totalSeconds variable accordingly.

We next determine how many seconds and minutes are left; pad the minutesDisplay and secondsDisplay with an extra zero if necessary; update the TextField (if one was passed into the constructor); and optionally trace out the time if we've set our test variable to true (handy for testing if you don't set a TextField).

The calculation used to determine the seconds variable takes the remainder of totalSeconds/60.The % (modulo) operator gives us the remainder.

The calculation used to determine the minutes variable simply takes the totalSeconds/60, rounded down using Math.floor().


Step 6: Coding the getTimeTotal() Function

Here we code a function that simply returns our timeTotal variable.Because we made this variable private we need a way to access it.

1
2
public function getTimeTotal():int
3
{
4
	return timeTotal;
5
}

Step 7: Coding the getTimeLoaded() Function

Here we code a function that returns our timeLoaded variable. Once again because it is private we need a way to access it.

1
2
public function getTimeLoaded():int
3
{
4
	return timeLoaded;
5
}

Step 8: Coding the getProg() Function

This function gives us the progress of our time.It is how much of the total time (that we set in the constructor) has passed. We multiply by 100 so we get a percentage between 1 and 100.

1
2
public function getProg():int
3
{
4
	return Math.floor(timeLoaded/timeTotal*100);
5
}

Step 9: Testing the CountTimer Class

Here we begin to design the main movie that uses our "CountTimer" class.

Go to File > New and create a new ActionScript 3.0 document.

Flash AS3 countdown timer stopwatch

Set the size to 320x220px.

Save this document as "Timer.fla". Go to File > New and choose Actionscript 3.0 Class.

Flash AS3 countdown timer stopwatch

Save this file as "Main.as". We are going to test our CountTimer class,so add the following to the "Main.as".

1
2
package
3
{
4
	import flash.display.MovieClip;
5
	import CountTimer;
6
	public class Main extends MovieClip{
7
	var countTimer:CountTimer;
8
	public function Main()
9
	{
10
		countTimer = new CountTimer(1,30,"up");
11
		countTimer.start();
12
	}
13
14
  }
15
16
}

Make sure you set the test variable in "CountTimer.as" to true, and set the movie's Document Class to "Main".

Press ctrl-enter and test the movie; you should see the time traced in the Output window.


Step 10: Designing the User Interface

Here we begin to design the main movie that uses our CountTimer class.

We will be using TweenLite in our movie so if you don't have a copy get it from greensock.com.


Countdown/Countup Text

Select the Text tool and make sure the following properties are set in the "CHARACTER" Panel.

  • Size: 50.0 pt
  • Color: Black
Flash AS3 countdown timer stopwatch

Still in the "Character" panel, click on "Embed" and make sure "UpperCase","LowerCase","Numerals" are selected, and under "Also include these characters"
that you have added a ":" and a "%".

Flash AS3 countdown timer stopwatchFlash AS3 countdown timer stopwatchFlash AS3 countdown timer stopwatch

Draw a textfield out on the stage and set the following properties under the "POSITION and SIZE" Panel.

  • X: 0
  • Y: 0
  • W: 320
  • H: 60
Flash AS3 countdown timer stopwatch

Give this TextField the instance name "timer_txt"; make sure the type is set to "Classic Text" and "Dynamic Text" respectively.

Flash AS3 countdown timer stopwatch

This TextField will be used to show the time when the movie first Starts.


Progress Bar

Now we need to design our progress bar.

Go to Insert > New Symbol. Give it the name "ProgressContainer" and make sure "Export for Actionscript" is checked and that the Class is set to "ProgressContainer".

Flash AS3 countdown timer stopwatchFlash AS3 countdown timer stopwatchFlash AS3 countdown timer stopwatch

Go to Window > Components and drag a ProgressBar component into the movie clip.

Flash AS3 countdown timer stopwatch

Set the ProgressBar's properties to the following.

  • X: 0
  • Y: 0
  • W: 320
  • H: 42.0

Under "Component Parameters" set mode to "manual".

Flash AS3 countdown timer stopwatch

Give the ProgressBar the instance name "pb".

Select the Text tool and make sure the following properties under the "CHARACTER" Panel are set.

  • Size: 30pt
  • Color: black

Draw a TextField into the movie clip.

Set the following properties on the TextField.

  • X: 80.0
  • Y: 1.0
  • W: 159.0
  • H: 38:0

Give this TextField the instance name "progress_txt".

You can now close this MovieClip.


Growing and Fading Text

Now we will design the growing and fading text, to be displayed when all the time has elapsed.

Go to Insert > New Symbol.Give it the name "GrowFadeText" and make sure "Export for Actionscript" is checked and the Class is set to "GrowFadeText".

Select the Text tool and make sure following properties are set under the "Character" Panel.

  • Size: 15pt
  • Color: [I set it to a blue, you can do the same if you wish]

Drag out a TextField into the MovieClip and set the following properties.

  • X: -69.0
  • Y: -6.35
  • W: 135.0
  • H: 21.0

Enter the text "TIMER COMPLETE" into the textField. You can now close this MovieClip.


Entry Fields

Now we will design the MovieClip that slides in from the left. Select the rectangle tool and set the color to white. Drag out a rectangle from the top left of the stage to the bottom right.

Select the rectangle you just dragged out and press F8.Give it the name "countContainer".Make sure "Export for Actionscript is checked and that Class is set to "countContainer".

Flash AS3 countdown timer stopwatchFlash AS3 countdown timer stopwatchFlash AS3 countdown timer stopwatch

Set the following properties on the MovieClip.

  • X: 322
  • Y: 0
  • W: 320
  • H: 220

Now double click to go inside the MovieClip.

Select the Text tool and make sure the following properties are set in the "CHARACTER" Panel.

  • Size: 50pt
  • Color: Black

Drag out a textfield onto the stage and set the following properties on it.

  • X: 0
  • Y: 0
  • W: 320
  • H: 60

Give this TextField the instance name "timer_txt" and make sure the type is set to "Classic Text" and "Input Text" respectively.

Once again select the Text tool and drag a TextField onto the stage.Then set the following properties on it.

  • X: 0
  • Y: 59.0
  • W: 320
  • H: 60

Give this TextField the instance name "instructions_txt" and make sure the type is set to "Classic Text" and "Input Text" respectively.

Go to Window > Components and drag three buttons inside this MovieClip.

Flash AS3 countdown timer stopwatch

Give the first button the instance name "countDown_btn" and set the following properties on it.

  • X: 14.00
  • Y: 160
Flash AS3 countdown timer stopwatch

Give the second button the instance name "cancel_btn" and set the following properties on it.

  • X: 103.00
  • Y: 160.00

Give the third button the instance name "countUp_btn" and set the following properties on it.

  • X: 182.00
  • Y: 160.00

You can now close the MovieClip.

Now that we have our UI Designed we can write the code for the main movie.


Step 11: Coding the Main Movie

If you are following along delete all the ActionScript in "Main.as" that you created in Step 9. That was for testing; now we need code that will work with our new interface.

Here we open the package declaration and import the classes we will be using.

Add the following to "Main.as".

1
2
package 
3
{
4
	import flash.display.MovieClip;
5
	import fl.controls.Button;
6
	import flash.text.TextField;
7
	import flash.events.TimerEvent;
8
	import flash.events.MouseEvent;
9
	import flash.text.TextFieldType;
10
	import flash.text.TextFieldAutoSize;
11
	import CountTimer;
12
	import com.greensock.TweenLite;
13
	import flash.events.Event;
14
	import fl.controls.ProgressBar;

Step 12: Variables and Constructor Function

Here we declare our variables and code the Constructor.

Add the following the the "Main.as"

1
2
public class Main extends MovieClip
3
{
4
	//An array to hold the minutes and seconds in elements [0] and [1]

5
	private var timeArray:Array;
6
	//Our countTimer

7
	private var countTimer:CountTimer;
8
	//A boolean that tells us whether this is the first timer

9
	//(the one used when the movie first starts)

10
	private var firstTimer:Boolean = true;
11
	//Direction of our timer can be "up" or "down"

12
	private var direction:String;
13
	//The MovieClip that contains the text we grow and fade

14
	private var growFadeText:GrowFadeText;
15
	//The MovieClip that holds our progressBar

16
	private var progressContainer:ProgressContainer;
17
	//The minutes

18
	private var min:int;
19
	//The second

20
	private var sec:int;
21
22
	public function Main()
23
	{
24
		min = 1;
25
		sec = 0;
26
		countTimer = new CountTimer(min,sec,"down",timer_txt);
27
		timer_txt.text = "1:00";
28
		countTimer.addEventListener(TimerEvent.TIMER_COMPLETE,timerComplete);
29
		setupButtons();
30
		addProgressContainer(0,70,"down");
31
		countTimer.start();
32
		stage.addEventListener(Event.ENTER_FRAME,updateProgress);
33
		cancel_btn.addEventListener(MouseEvent.CLICK,moveContainer);
34
	}

First we set up the min and sec variables and pass them to the countTimer; we then set the direction to "down" and set the target TextField to timer_txt.

We then set some default text for the TextField,add an TIMER_COMPLETE event to the Timer, run a function to set up our buttons,add the ProgressBar,start the Timer, and add an ENTER_FRAME event listener to the stage (which we'll use to update the progress bar), and finally add a CLICK event listener to our cancel_btn.


Step 13: Coding the timerComplete() Function

Add the following to "Main.as".

1
2
private function timerComplete(e:TimerEvent):void
3
{
4
	addGrowFadeText(154,130);
5
6
	if (firstTimer == true)
7
	{
8
		TweenLite.to(growFadeText, 2.5, {scaleX:2, scaleY:2,alpha:0,onComplete:moveContainer});
9
	}
10
	else
11
	{
12
		TweenLite.to(growFadeText, 2.5, {scaleX:2, scaleY:2,alpha:0,onComplete:showTheControls});
13
	}
14
}

Here we add the text to the stage by calling addGrowFadeText() we will examine this function shortly.We then check the firstTimer variable to see if this is the first timer, if it is use tweenLite to grow and fade the text and call the moveContainer function once the animation completes.If it not the first timer then we once again use tweenLite to grow and fade the text but call the showTheControls() function once the animation completes.We will examine the moveContainer and showTheControls functions shortly.


Step 14: Coding the setupButtons() Function

Add the following to "Main.as"

1
2
private function setupButtons():void
3
{
4
	countContainer.countDown_btn.addEventListener(MouseEvent.CLICK,doTimer);
5
	countContainer.countUp_btn.addEventListener(MouseEvent.CLICK,doTimer);
6
	countContainer.cancel_btn.addEventListener(MouseEvent.CLICK,restoreControls);
7
	countContainer.instructions_txt.text = "Enter time in format 1:30 then press CountDown or CountUp button";
8
	//We dont want user to be able to edit the text

9
	countContainer.instructions_txt.selectable = false;
10
11
}

Here we add some EventListeners to our Buttons, set the text for our instructions_txt and set it so the user cannot select or edit the text. I used a TextField here to keep this already long tutorial shorter, but you would probably want to use a Label component here and style it with a TextFormat Object.


Step 15: Coding the addProgressContainer() Function

Add the following to "Main.as"

1
2
private function addProgressContainer(xPos:int,yPos:int,dir:String):void
3
{
4
	progressContainer = new ProgressContainer();
5
	progressContainer.x = xPos;
6
	progressContainer.y = yPos;
7
	stage.addEventListener(Event.ENTER_FRAME,updateProgress);
8
	addChild(progressContainer);
9
	if (dir == "down"){
10
		progressContainer.pb.direction = "left";
11
	} else {
12
		progressContainer.pb.direction = "right";
13
	}
14
}

Here we create a new progressContainer and set its x and y properties by the xPos and yPos parameters that are passed in.We then add an ENTER_FRAME event listener that calls the updateProgress() function, and we add the progressContainer to the stage.Finally we check the dir parameter to see if it is equal to "down"; if it is we set the ProgressBar's direction to "left", otherwise we set the ProgressBar's direction to "right".


Step 16: Coding the removeProgressContainer() Function

Add the following to "Main.as"

1
2
private function removeProgressContainer():void
3
{
4
	if (progressContainer != null)
5
	{
6
		stage.removeEventListener(Event.ENTER_FRAME,updateProgress);
7
		removeChild(progressContainer);
8
		progressContainer = null;
9
	}
10
}

Here we check whether the progressContainer exists; if it doesn't, then we remove the ENTER_FRAME event listener from the stage so it does not continue to run.We then remove the progressContainer from the stage and set it to null since we are done with it.


Step 17: Coding the updateProgress() Function

Add the following to "Main.as".

1
2
private function updateProgress(e:Event):void
3
{
4
	progressContainer.progress_txt.text = countTimer.getProg().toString() + "%";
5
	progressContainer.pb.setProgress(countTimer.getTimeLoaded(),countTimer.getTimeTotal());
6
}

Here we set the progress_txt's text to show the progress of our timer.We use the countTimer's getProg() method which returns an integer of what percentage of the time has passed.Since it returns an int we use AS3's built in toString() method on it,and append a "%" sign to it.

Next we call the setProgress() method of the ProgressBar component on our ProgressBar (pb). We pass in countTimer.getTimeLoaded() and countTimer.getTimeTotal() which return integers. To learn more about the ProgressBar component check out my Quick Introduction to the ProgressBar component.


Step 18: Coding the addGrowFadeText() Function

Add the following to "Main.as".

1
2
private function addGrowFadeText(xPos:int,yPos:int)
3
{
4
	growFadeText = new GrowFadeText();
5
	growFadeText.x = xPos;
6
	growFadeText.y = yPos;
7
	addChild(growFadeText);
8
}

Here we create a new instance of GrowFadeText, set its x and y properties as specified, and then we add it to the stage.


Step 19: Coding the removeGrowFadeText() Function

Add the following to "Main.as".

1
2
private function removeGrowFadeText():void
3
{
4
	if (growFadeText != null)
5
	{
6
		removeChild(growFadeText);
7
		growFadeText = null;
8
	}
9
}

Here we check to see whether growFadeText exists. If it doesn't, we remove it from the stage and set it to null.


Step 20: Coding the moveContainer() Function

Add the folowing to "Main.as".

1
2
private function moveContainer(e:Event=null):void
3
{
4
	countTimer.stop();
5
	removeChild(timer_txt);
6
	removeChild(cancel_btn);
7
	removeGrowFadeText();
8
	removeProgressContainer();
9
	countContainer.cancel_btn.visible = false;
10
	firstTimer = false;
11
	TweenLite.to(countContainer, 1, {x:0});
12
}

Here we stop the timer and remove the timer_txt and cancel_btn. Next we call our removeGrowFadeText() and removeProgressContainer() functions, set the cancel_btn within the countContainer to be invisible, set the firstTimer variable to false, and slide the countContainer in using TweenLite.


Step 21: Coding the showControls() Function

Add the following to "Main.as":

1
2
private function showTheControls():void
3
{
4
	showControls();
5
	removeProgressContainer();
6
	countTimer.stop();
7
	countContainer.timer_txt.text = "";
8
	countContainer.timer_txt.text = "";
9
}

Here we call the showControls function, which we will examine shortly. Next we call removeProgressContainer(), stop the timer and reset our TextFields to be blank.


Step 22: Coding the doTimer() Function

Add the following to "Main.as":

1
2
private function doTimer(e:MouseEvent):void
3
{
4
	if (e.target == countContainer.countDown_btn)
5
	{
6
		direction = "down";
7
	}
8
	else
9
	{
10
		direction = "up";
11
	}
12
	if (countContainer.timer_txt.text != "")
13
	{
14
		timeArray = countContainer.timer_txt.text.split(":");
15
		min = timeArray[0];
16
		sec = timeArray[1];
17
		countTimer = new CountTimer(min,sec,direction,countContainer.timer_txt);
18
		countTimer.start();
19
		countTimer.addEventListener(TimerEvent.TIMER_COMPLETE,timerComplete);
20
		countTimer.addEventListener(TimerEvent.TIMER,updateProgress);
21
		hideControls();
22
		addProgressContainer(0,70,direction);
23
	}
24
}

We first check to see which button was pressed.If the countDown_btn was pressed we set the direction variable to "down" otherwise the we set the direction variable to "up".Next we check to make sure timer_txt is not blank.If it is not then we use the split() function to put the minutes and seconds into the timeArray.The split() function takes a string and separates it by whatever you pass it as a parameter -- here we used the colon (:) -- and then adds each "piece" to the array. So, if you passed in "1:45", then the array's element [0] would be "1"; element [1] would be "45".

We then set the sec and min variables.

Next we create a new instance of the countTimer and pass in the min,sec,dir,and the TextField to use.

We then add two TimerEvent listeners that call our timerComplete() and updateProgress() functions.

Finally we call the hideControls() function and add the progressContainer to the stage.


Step 23: Coding the showControls() Function

Add the following to "Main.as".

1
2
private function showControls():void
3
{
4
	countContainer.instructions_txt.visible = true;
5
	countContainer.countDown_btn.visible = true;
6
	countContainer.countUp_btn.visible = true;
7
	countContainer.cancel_btn.visible = false;
8
}

Here we simply set the instruction_txt,countDown_btn,and countUp_btn to be visible. We then set the cancel_btn to be invisible.


Step 24: Coding the hideControls() Function

Add the following to "Main.as".

1
2
private function hideControls():void
3
{
4
	countContainer.instructions_txt.visible = false;
5
	countContainer.countDown_btn.visible = false;
6
	countContainer.countUp_btn.visible = false;
7
	countContainer.cancel_btn.visible = true;
8
}

This is the opposite of the previous function; here we just set the set the instruction_txt,countDown_btn,and countUp_btn to be invisible. We then set the cancel_btn to be visible.


Step 25: Coding the restoreControls() Function

Add the following to "Main.as".

1
2
private function restoreControls(e:Event)
3
{
4
	showTheControls();
5
	countTimer.stop();
6
}

Here we call the showControls() function and stop the timer.


Step 26: Close the Class and Package.

Add the following to "Main.as"

1
2
	}//Close the Class

3
4
}//Close the Package

Here we close out our class and package.


Step 27: Set the Document Class and Test the Movie

Although not absolutely necessary,set the test variable to false in the "CountTimer".as".

Make sure your Document Class is set to "Main" and test the Movie.


Conclusion

We now have a versatile Timer Class that can be used for any number of things, from time limits on tests to setting times for levels on games.

I hope you found this tutorial useful and thanks for reading!

Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.