Update (December 11th, 2008): The source code is available for download now. The zip archive also includes a FlashDevelop project file. Get it here.
This tutorial may serve as a beginner exercise in AS3 coding. But before starting, let’s take a quick look at what we will be creating:
The spinning preloader animation is an all-time classic. Our implementation will be highly configurable. You will be able to set the number, size, color and fade-out duration of the rectangular segments, as well as the radius and the spinning speed.
Prerequisites
Since this is a pure AS3 project, you can choose whatever IDE you like. I use the open-source AS3 IDE FlashDevelop along with the free Flex 3 SDK. The only other thing we need is the AS3 animation kit TweenLite. This lightweight tweening engine is contained in a single class file. You can eiher copy and paste it into your project space, or you can store it somewhere else and add the path to your project’s classpaths settings.
I call the preloader class SpinningPreloader and use com.log2e.utils as package definition. So my FlashDevelop project panel looks like this:

The SpinningPreloader Class
Here’s the full class code (I will explain it below):
-
package com.log2e.utils
-
{
-
import flash.display.DisplayObjectContainer;
-
import flash.display.Sprite;
-
import flash.events.TimerEvent;
-
import flash.utils.Timer;
-
import gs.TweenLite;
-
-
public class SpinningPreloader extends Sprite
-
{
-
private var _target
isplayObjectContainer; -
private var _container:Sprite;
-
private var _centerX:uint;
-
private var _centerY:uint;
-
private var _radius:uint;
-
private var _steps:uint;
-
private var _rectWidth:uint;
-
private var _rectHeight:uint;
-
private var _color:uint;
-
private var _count:uint;
-
private var _timer:Timer;
-
private var _timerInterval:uint;
-
private var _fadeOutDuration:Number;
-
-
public function SpinningPreloader( target
isplayObjectContainer, -
centerX:uint = 0,
-
centerY:uint = 0,
-
radius:uint = 15,
-
steps:uint = 24,
-
rectWidth:uint = 4,
-
rectHeight:uint = 2,
-
color:uint = 0x0000FF,
-
timerInterval:uint = 20,
-
fadeOutDuration:Number = 1.5 )
-
{
-
_target = target;
-
_centerX = centerX;
-
_centerY = centerY;
-
_radius = radius;
-
_steps = steps;
-
_rectWidth = rectWidth;
-
_rectHeight = rectHeight;
-
_color = color;
-
_timerInterval = timerInterval;
-
_fadeOutDuration = fadeOutDuration;
-
}
-
-
public function start():void
-
{
-
_container = new Sprite();
-
_container.x = _centerX;
-
_container.y = _centerY;
-
_target.addChild(_container);
-
-
_count = 0;
-
_timer = new Timer(_timerInterval, 0);
-
_timer.addEventListener(TimerEvent.TIMER, drawRectangle);
-
_timer.start();
-
}
-
-
public function stop():void
-
{
-
if (_container)
-
{
-
TweenLite.to( _container, .5, { alpha:0, onComplete:onContainerFadeOutComplete } );
-
}
-
}
-
-
private function onContainerFadeOutComplete():void
-
{
-
_timer.stop();
-
_target.removeChild(_container);
-
}
-
-
private function onRectFadeOutComplete(rect:Sprite):void
-
{
-
_container.removeChild(rect);
-
}
-
-
private function drawRectangle(e:TimerEvent):void
-
{
-
var rot:Number = _count * 360 / _steps;
-
var rect:Sprite = filledRectangle(_rectWidth, _rectHeight, _color);
-
rect.x = _radius * Math.cos(rot * Math.PI/180);
-
rect.y = _radius * Math.sin(rot * Math.PI/180);
-
rect.rotation = rot;
-
_container.addChild(rect);
-
_count++;
-
-
TweenLite.to( rect, _fadeOutDuration, { alpha:0, onComplete:onRectFadeOutComplete, onCompleteParams:[rect] } );
-
e.updateAfterEvent();
-
-
if (_count == _steps)
-
{
-
_count = 0;
-
}
-
}
-
-
private function filledRectangle(width:uint, height:uint, color:uint):Sprite
-
{
-
var rect:Sprite = new Sprite();
-
rect.graphics.beginFill(color);
-
rect.graphics.drawRect(-width/2, -height/2, width, height);
-
rect.graphics.endFill();
-
return rect;
-
}
-
-
}
-
}
The Constructor
The constructor receives a list of parameters:
- target: The display object you want to attach the preloader animation to. The type is
DisplayObjectContainerso the target can be any object that inherits from this class (for exampleStage,MovieClip,Sprite). - centerX: The x position of the preloader’s center point.
- centerY: The y position of the preloader’s center point.
- radius: The radius of the preloader. Please note that this is not the outer radius of the resulting animation but the distance between the center point and the registration point of the rectangular segments.
- steps: The number of rectangles that are created in one full turn.
- rectWidth: The width of a single rectangular segment.
- rectHeight: The height of a single rectangular segment.
- color: The color of the rectangles.
- timerInterval (in ms): This parameter controls the speed of the rotation by setting the time interval after which a new rectangle is drawn.
- fadeOutInterval (in s): This parameter specifies the duration of the alpha tween that fades out it each segment.
The start() and stop() Methods
These two methods are the only interface between the SpinningPreloader class and the outside world.
The start() method creates a container for the animation and positions it on the target display object. It also initializes the _count property and starts the timer which repeatedly calls the drawRectangle() method.
The stop() method fades out the container sprite. Once the alpha value is 0 the timer is stopped and the container is removed from the display list. If you prefer to remove the animation immediately just replace the line of code that starts the tween with the two lines from the onContainerFadeOutComplete() event handler method.
The “Fading” Event Handlers
The method onContainerFadeOutComplete() is called after the container’s alpha value has reached 0.
The method onRectFadeOutComplete() is called whenever a single rectangle has finished its life cycle. As soon as the rectangle’s alpha value is 0 it is removed from the display list. This way we limit the maximum number of rectangles that are child objects of the container sprite at the same time.
Drawing the Rectangles
The angle that defines the position of each rectangle is calculated with the help of a counter variable (_count) which is incremented each time a rectangle is drawn. If the counter value is equal to the number of steps _count is reset to zero. The result from 360 divided by the number of steps muliplied with _count gives us the angle in degrees. This value is stored in the local variable rot.
In order to calculate the exact x and y coordinates we need a little trigonometry.

(Just on a side note, we use the three o’clock position as starting point because that’s where the 0 degree angle is situated in Flash.) The sine and cosine in the above diagram are calculated by sin(A) = y/r and cos(A) = x/r. This trigonometric relation is used in the drawRectangle() method:
rect.x = _radius * Math.cos(rot * Math.PI/180);
rect.y = _radius * Math.sin(rot * Math.PI/180);
Please note that the Math.sin() and Math.cos() functions expect the angle to be in radians, that’s why we have to multiply rot with Math.PI/180.
The rectangles themselves are created in the filledRectangle() method which receives the width, height and color as parameters. The sprite instance is returned to drawRectangle() where the x, y and rotation values are set and the rectangle is added to the display list. As soon as the rectangle is visible it starts to fade out. Invoking e.updateAfterEvent() causes the Flash Player to update the screen immediately after a rectangle has been added (instead of relying on the next scheduled screen update that is governed by the frame rate).
Using the SpinningPreloader Class
The animations shown on this page were created by instantiating three preloader objects with different parameters:
-
package
-
{
-
import flash.display.Sprite;
-
import com.log2e.utils.SpinningPreloader;
-
-
public class Main extends Sprite
-
{
-
public function Main():void
-
{
-
var pl1:SpinningPreloader = new SpinningPreloader(this, 50, 70, 15, 24, 4, 2, 0x0000FF, 20, 1.5);
-
pl1.start();
-
-
var pl2:SpinningPreloader = new SpinningPreloader(this, 180, 70, 40, 48, 8, 3, 0xFF0000, 30, 2);
-
pl2.start();
-
-
var pl3:SpinningPreloader = new SpinningPreloader(this, 330, 70, 30, 32, 12, 4, 0×999999, 15, 1);
-
pl3.start();
-
}
-
}
-
}
Room for Improvement
Where to go from here? There are several options for improving the class. For example, you could add a text field at the center of the preloader and an update function that receives the loading progress value. Or you could use a circle or a small bitmap instead of the rectangle. I will leave this as an exercise to you.
If you have any questions or suggestions leave a comment or drop me a message.
Tags: ActionScript, Flash, FlashDevelop, Preloader
This is the most usefull tutorial I’ve ever read. I’m a newby in flash, and the DisplayObjectContainer was like finding gold for my intent of making a reusable preloader. Thanks so much.
I am trying out your tutorial but I’m getting an error.
Line 32: 1084: Syntax error: expecting rightparen before 0000.
Any ideas?
@Steve: Well, it’s just a syntax error, so take a closer look at your code again. It’s probably a missing closing brace or an omitted parenthesis.
I too am trying to figure out what bracket or parenthesis is missing….
I’m having a hard time getting this to work. Is there any way you could post the .fla for download?
I’m also having difficulty dealing with the package call.
There isn’t a bracket or parenthesis missing, the webpage changed a lowercase x to alt+0215 “×” in the color code.
Uenuku,
That was It! Thank you
How do you go about integrating this with loading an image or something so that all the lines are shown? The way I have it right now it skips most of them since the image loads fast and doesn’t have time to count each percent number.
I’d really like to add this to my library but I’m not getting the final step for implementation. I guess I’m below “beginner.” Without a sample .fla, I’ll just have to store this away for another day.
I appreciate this tutorial but really need to agree with the others who mention the final step is puzzling. I’m completely new to AS3 and OOP, and while I appreciate a good challenge, it would be cool to have some closure on this awesome class!
Thanks man, this is superb!
Is there a reason why SpinningPreloader extends Sprite ? It doesnt seem like itself gets added to the display list.
@Ivo: Good eye! You are right, the class SpinningPreloader doesn’t necessarily have to extend Sprite. I guess I had originally planned to make it a display object itself. The _target property makes this obsolete though. Thanks for pointing this out.
Very usefull post.
Thanks.
P.S. I like your writing style.
First of all congratulation for such a great site. I learned a lot reading article here today. I will make sure i visit this site once a day so i can learn more.
That is really impressive, But unless there is a .fla file, it’s difficult to get what your doing.
Could you submit the .fla file and or have a link to the file it’s easier to understand files when pulling them apart.
@Jill: You can easily create the .fla file yourself: Create a new file in Flash CS3/CS4 and assign the “Main” class from the ZIP archive (http://blog.log2e.com/demos/spinning-preloader/SpinningPreloader.zip) as document class.
Would this be very hard without using the TweenLite library ? I’m trying to adapt the code and use the tween class but appearently this is harder than i thought…
Ok I’ve managed to get it (partly) working. Changed the object to a circle and replaced the tweenlite functions with AS3 Tweens.
A problem appeared though, when I added a TweenEvent.MOTION_FINISH for the onFadeOutComplete function. After a while the animation seems to freeze or stop working, the objects stop fading out.
It looks likes this is a garbage collector problem, but using an array for the tweens that i reset when it reaches the _count variable, and removing the tween event listeners don’t fix this problem. Anyone got an idea how to fix this ?
Hi all!
My name is Steven and Im new around here
. So far this is an excellent place for information and I’ve spent quite a bit of time reading and browsing around. Look forward to hearing from you!
Man, thanks so much for this! Awesome and lite!
sd
This is awesome !!! Good work
@Rob
Use tweenlite, that’ll fix the problem.
Can anyone help me pls?
I am doing some papervision animation….i created my main class and evything works perfectly….now i want a preloader,but i do not know how to implement preloaders on .as files,better said how to make it wait until whole animation is loaded and then to start it…i am using flash cs3,and i hav created .fla file which uses only one .as file as docment class….
If anyone understood what i mean…pls…this is killing me
Very nice.
Your code is flawed, but it would be very easy to fix it. Your event listener is never removed. Therefore, your timer will never be garbage collected and neither will your preloader.
A memory leak!
Thanks for the awsome post, i like the way u describe the session.
i was looking for one for some time.
Long time viewer / first time poster. Really enjoy reading the blog, keep up the excellent work. Will definitely start posting more in the future.
I know this is well documented and you are a very nice human beeing sharing it with a big community and you don’t need to do that.
But I’m a helpless little piece of crap in AS3 and I need to know how to implement the loader class: After hours of trying it would be better for me if you were less well-intentioned.