AS3 – Draw Circle Animation Based on Time

If you need to perform an animation and have it be standard when viewed across different machines, it is best to use an onEnterFrame event. I had a need in a project recently to draw a circle in a specified amount of time. I had been using the Timer class but found major time discrepancies between running the code locally and running the code in a browser. With some code that Jackson Dunstan provided, I was able to modify the animation so that you can start/stop drawing the circle based on user input. (In the sample provided it is by clicking the stage) I hope this helps someone in a similar situation. Code after the jump…

  Draw a circle with as3 that will finish in a specific time. (9.6 KiB, 630 hits)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package
{
	import flash.display.*;
	import flash.events.*;
	import flash.utils.*;
 
	[SWF(backgroundColor=0xEEEADB,frameRate=30)]
 
	/**
	*   Draws a circle using AS3 and you can start/stop the animation by clicking the stage
	*   @author Jackson Dunstan w/ mods by jguthrie
	*/
	public class CircleDrawTest extends Sprite
	{
		/** Current angle on the circle we're drawing from */
		private var __angle:Number;
 
		/** Center of the circle in the X */
		private var __centerX:Number;
 
		/** Center of the circle in the Y */
		private var __centerY:Number;
 
		/** Radius of the circle */
		private var __radius:Number;
 
		/** Number of radians of the circle to draw per second */
		private var __radiansPerSecond:Number;
 
		/** Time circle drawing will finish */
		private var __endTime:int;
 
		/** Last time we entered a frame */
		private var __lastFrameTime:uint;
 
		/** Our circle*/
		private var __circle:Shape = new Shape();
 
		/** Parameter used in stageClick to know if we are paused or not */
		private var __paused:Boolean = false;
 
		/** Double this time is how long it will take for the circle to be drawn */
		private var __rotationTime:int = 4;
 
		/** Parameter that is used to know when to reset the __timeSpentPaused variable after a pause */
		private var __iWasPaused:Boolean = false;
 
		/** Variable that is used to add onto __endTime when you pause the animation */
		private var __timeSpentPaused:int;
 
		/** */
		private var __beforeTime = int;
 
		/**
		*   Application entry point
		*/
		public function CircleDrawTest()
		{
			stage.addEventListener(MouseEvent.CLICK, stageClick);
 
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.quality = StageQuality.BEST;
			addChild(__circle);
 
			var mask_sh:Shape = new Shape();
			mask_sh.graphics.beginFill(0xCCCCCC);
			mask_sh.graphics.drawCircle(0, 0, 31);  //make the mask just a bit larger than the circle
			mask_sh.graphics.endFill();
			mask_sh.x = stage.stageWidth/2;
			mask_sh.y = stage.stageHeight/2;
			addChild(mask_sh);
 
			__circle.mask = mask_sh;
 
			__angle = 270*(Math.PI/180);
			__centerX = stage.stageWidth/2;
			__centerY = stage.stageHeight/2;
			__radius = 29;
			__radiansPerSecond = Math.PI / __rotationTime;
 
			initCircle();
		}
 
		private function stageClick(e:Event):void
		{
			if (__paused == true) {
				__timeSpentPaused = getTimer() - __timeSpentPaused;
				__endTime = __endTime + __timeSpentPaused;
				__lastFrameTime = getTimer();
				__iWasPaused = false;
				__paused = false;
				addEventListener(Event.ENTER_FRAME, onEnterFrameDraw);
 
			} else {
				removeEventListener(Event.ENTER_FRAME, onEnterFrameDraw);
				__timeSpentPaused = getTimer();
				__iWasPaused = true;
				__paused = true;
			};
		}
 
		private function initCircle():void 
		{
			__beforeTime = getTimer();
			__angle = 270*(Math.PI/180);
			__endTime = getTimer() + (2000*Math.PI) / __radiansPerSecond;
 
			__circle.graphics.clear();
			__circle.graphics.lineStyle(6, 0xFF6600,1,false,LineScaleMode.NORMAL,CapsStyle.NONE);
			__circle.graphics.moveTo(
				__centerX + Math.cos(__angle)*__radius,
				__centerY + Math.sin(__angle)*__radius
			);
 
			addEventListener(Event.ENTER_FRAME, onEnterFrameDraw);
			__lastFrameTime = getTimer();
		}
 
		/**
		*   Callback for when a frame is entered
		*   @param ev ENTER_FRAME event
		*/
		private function onEnterFrameDraw(ev:Event): void
		{
			var now:int = getTimer();
			var dTime:int = now - __lastFrameTime;
 
			if (!__iWasPaused) {
				__lastFrameTime = now;
			}
 
			var radiansMoved:Number = dTime * 0.001 * __radiansPerSecond;
			var endAngle:Number = __angle + radiansMoved;
			var halfAngle:Number = __angle + radiansMoved*0.5;
			__angle = endAngle;
 
			__circle.graphics.curveTo(
				__centerX + Math.cos(endAngle)*__radius,
				__centerY + Math.sin(endAngle)*__radius,
				__centerX + Math.cos(halfAngle)*__radius,
				__centerY + Math.sin(halfAngle)*__radius
			);
 
			if (now > __endTime)
			{
				removeEventListener(Event.ENTER_FRAME, onEnterFrameDraw);
				//trace('Total time elapsed : ' + (getTimer() - (__beforeTime + __timeSpentPaused))); //Not accurate if paused
				initCircle();
			}
		}
	}
}
  1. Thanks for giving me credit. It’s good to see where you’ve taken it and even better to see it posted for everyone’s benefit. Congrats on getting it to work!

    • Bams
    • January 25th, 2012

    Hi!

    first sorry for my bad english, but am french!!
    thank you for sharing this useful code.

    But, please, could you help me transposing it for a preloader!

    I promise I spent a lot of time trying to analyse this code and do it myself, but I failed ;-)

    see you!
    :-)

    • Hey mate, you may want to just do some googling and get one. This one is quite good: http://www.smithmediafusion.com/blog/?p=420

        • Bams
        • January 26th, 2012

        Hey Jeff,

        well, I’ve already found some .fla files like this but they’re all based on a drawing (and mask) made directly in Flash then simply tweened on the timeline.

        what I’d really like is a ‘full dynamic as3′ animated circle!
        you’re code above does almost the job, but it’s based on the EnterFrame Event or I’d like to use bytesLoded stuff instead of the EnterFrame and getTimer..

        not sure I’m clear, and I don’t want to bother you too much with my problem..

        if you have an idea, let me know!

        thanks again.
        Seb

  1. No trackbacks yet.

 

Switch to our mobile site