Draw an Arc with ActionScript
Drawing an arc (a segment of a circle’s circumference) is very similar to drawing a complete circle. Just like drawing a circle, drawing an arc requires you to specify the center, the radius, and the number of steps to take from the first point to the last. But drawing an arc also requires additional information such as the angle of the first point on the arc, the direction (clockwise or counter-clockwise) to travel around the circle’s circumference, and the angle of the last point on the arc.
So the arguments in our “drawArc” function might look something like this:
function drawArc (centerX, centerY, radius, startAngle, endAngle, direction, steps){
//
That isn’t too bad, but it could be better. The “endAngle” and the “direction” arguments could be combined into one “arcAngle” argument. That way we can say, “Start at an angle of 45 degrees then sweep counter-clockwise 90 degrees” rather than, “Start at an angle of 45 degrees then go counter-clockwise until you get to 315 degrees.” Our modified arguments would look like this:
function drawArc (centerX, centerY, radius, startAngle, arcAngle, steps){
//
If you read my previous article you probably understand that drawing a circle involves moving through a series of points and that each point is described by its angle from center. The angle can be described using degrees, radians or a ratio. I prefer using a ratio from 0 to 1 as it’s simple and easily converted to any other unit of measurement such as degrees or radians.
Example: A quarter of a full rotation can be represented in any number of ways: 90 degrees, 25%, 1/2 Math.PI radians, or as .25 when expressed as a ratio from 0 to 1. Using a ratio has the benefit of abstracting your data and removing “arbitrary” numbers such as 360, 100, 2*Math.PI, 2 to the 64th power, etc. To convert from a ratio to any other unit of measure, simply multiply the ratio times the number of units in one full rotation.
Now that we have our arguments all set up and know how they’ll be formatted, it’s time to move on to writing the actual guts of the code which will be responsible for drawing the arc. Using the knowledge gained in the previous circle article you should understand how to plot any point on a circle’s circumference as long as you know its angle from center. Since we can draw any point at a given angle and we know the arguments we’ll be using, writing the “drawArc” function is as easy as determining the angle of each point on the arc and then plotting its position.
// Angles are expressed as a number between 0 and 1. .25 = 90 degrees.
// If you prefer using degrees, write 90 degrees like so "90/360".
function drawArc(centerX, centerY, radius, startAngle, arcAngle, steps){
//
// For convenience, store the number of radians in a full circle.
var twoPI = 2 * Math.PI;
//
// To determine the size of the angle between each point on the
// arc, divide the overall angle by the total number of points.
var angleStep = arcAngle/steps;
//
// Determine coordinates of first point using basic circle math.
var xx = centerX + Math.cos(startAngle * twoPI) * radius;
var yy = centerY + Math.sin(startAngle * twoPI) * radius;
//
// Move to the first point.
moveTo(xx, yy);
//
// Draw a line to each point on the arc.
for(var i=1; i<=steps; i++){
//
// Increment the angle by "angleStep".
var angle = startAngle + i * angleStep;
//
// Determine next point's coordinates using basic circle math.
xx = centerX + Math.cos(angle * twoPI) * radius;
yy = centerY + Math.sin(angle * twoPI) * radius;
//
// Draw a line to the next point.
lineTo(xx, yy);
}
}
//
// Set a line style so we can see what we are drawing.
lineStyle(0, 0xFF0000);
//
// Draw an arc with a center of (250, 250) and a radius of 200
// that starts at an angle of 45 degrees then rotates counter-
// clockwise 90 degrees. We'll span the arc with 20 evenly spaced points.
drawArc(250, 250, 200, 45/360, -90/360, 20);
//
The above code produces the following SWF file:
That may or may not be what you were expecting to see. The thing to note about the above SWF is that the point with no angle of rotation (0 degrees) is at the 3 o'clock position. Moving the the angle to better suit your needs is a very simple matter. If you want the point with no rotation to be at 12 o'clock you subtract .25 (a quarter of a turn) from your start angle like so:
function drawArc(centerX, centerY, radius, startAngle, arcAngle, steps){
//
// Rotate the point of 0 rotation 1/4 turn counter-clockwise.
startAngle -= .25;
//
var twoPI = 2 * Math.PI;
var angleStep = arcAngle/steps;
var xx = centerX + Math.cos(startAngle * twoPI) * radius;
var yy = centerY + Math.sin(startAngle * twoPI) * radius;
moveTo(xx, yy);
for(var i=1; i<=steps; i++){
var angle = startAngle + i * angleStep;
xx = centerX + Math.cos(angle * twoPI) * radius;
yy = centerY + Math.sin(angle * twoPI) * radius;
lineTo(xx, yy);
}
}
lineStyle(0, 0xFF0000);
drawArc(250, 250, 200, 45/360, -90/360, 20);
//
The above code produces the following SWF:
So there you have it. All the code needed to draw an arc or plot the points along a segment of a circle's circumference. If you're looking for an easy challenge, try modifying the code so it draws a wedge (like a slice of pie) rather than an arc.
Update: The next tutorial in this series is How to Swing a Pendulum Arc.
[…] to http://www.pixelwit.com/blog/2007/07/draw-an-arc-with-actionscript/ for the arc drawing […]
Thanks for this excellent article. This saved me lot of time
For anyone having trouble with properties not found …
I added all the var’s after drawArc( … as Number’s, and in front of ‘moveTo, lineTo and lineStyle’ I added graphics.
Hope that helps.
Hi,
This has been really useful to me as someone very new to Flash and Actionscript. But while it works for me in Actionscript 2, when I try to load it in Actionscript 3 I get an error “1180: Call to a possibly undefined method lineTo” on moveTo, lineTo, and lineStyle. Does anyone know why this is, and what I would need to do to fix it for Actionscript 3?
Thanks a bunch!
J.
When I first used this code I got some unexpected results, because I expected the arc angle parameter to move anticlockwise. Normally 0 is right, 90 (pi/2) is up, 180 (pi) is left, and 270 (3pi/4) is down. Therefore increasing values go anticlockwise. The code as is requires a negative arcAngle to go anticlockwise. To correct this the calculated yy values should subtract the sine value instead of add. This results in positive arcAngle values to be anticlockwise and negative arcAngle values to be clockwise which conforms to normal mathematical conventions. (http://en.wikipedia.org/wiki/Angle#Positive_and_negative_angles)
[…] A recent comment on my Oval Drawing Tutorial asks how to “give the appearance that an oval is being drawn slowly”. Hmmm… this sounds like a job for my handy Arc Drawing Function. […]
Great piece of code, thanks a lot! Tbh I don’t see why this is not in the AS3 api as a standard function, since it is available in the GUI as a tool.
@mrkrstft, I just so happen to have a tutorial explaining how to draw an arc using an onEnterFrame function.
Great tutorial, been looking this all day. But I want to animate the arc to be draw during a second or so. I have put the call to drawArc in a onEnterFrame function but it still shows the whole arc at once. Can you help me?
Hi,
Thanks for such a great work.
i have one more problem attached to this.
i have few images and i want to move those images along with an arc.
Can you please help me in doing that?
Thanks,
kanu
Hi, in the argument to sin and cos, you should be multiplying the angle by Math.PI/180.0 instead of multiply by 2*Math.PI.
[…] you’re new to drawing arcs I suggest reading my previous circle and arc tutorials for an introduction to trigonometry in […]
After noticing the link to your code, I can see the problem. Rather than drawing a single thick line to make one arc segment, draw 2 arcs connected with 2 lines to make a shape.
@Tyler, It looks like you may be rotating the arc segments. Each segment should have 0 rotation when in its final position and you should also check to be sure that adjacent segments share the exact same points with their neighbors. Flash draws with amazing accuracy as long as you give it accurate input (same points, scale, rotation, etc.).
@PixelWit
Thank you very much for responding so quickly. I apologize for not being as descriptive as I’ve been.
What I am trying to do is create a circular nav. The size of each piece of the circle will be a different color and size.
I bumped up the size some, however, it then causes some overlap – which if the navigation uses any blend modes or opacity.. becomes quite distracting.
Is their any way to make the arcs flush? (without any overlaps or gaps?)
Here is a screen cap of what I am getting:
http://dev.tylerc.net/circle/screenshot_01.png
Here is part of the code that is generating this:
http://dev.tylerc.net/circle/code.txt
Again, Thank you very much! I really appreciate you even looking at this as I’m sure you are very busy.