Reputation: 30158
I'm trying to draw an arc in flash using a minimal amount of code / iterations. I ported this method below from an old AS2 example, but it requires a loop through a number of steps to make it look smooth, and I'd rather avoid that. I saw AS3 has a "curveTo" command, but it doesn't really draw a circular arc, it draws a bezier curve. Is there an arc command in flash? or a way to draw a segment of a circle?
Here's my old code:
function drawSolidArc (drawObj:Object, centerX:Number,centerY:Number,innerRadius:Number,outerRadius:Number,startAngle:Number,arcAngle:Number,steps:int=20):void {
if (Math.abs(startAngle)>360)startAngle%=360
if (Math.abs(arcAngle)>360)arcAngle%=360
startAngle/=360,arcAngle/=360
var twoPI:Number = 2 * Math.PI;
var angleStep:Number = arcAngle/steps;
var angle:Number, i:int, endAngle:Number;
var xx:Number = centerX + Math.cos(startAngle * twoPI) * innerRadius;
var yy:Number = centerY + Math.sin(startAngle * twoPI) * innerRadius;
var xxInit:Number=xx;
var yyInit:Number=yy;
drawObj.graphics.moveTo(xx,yy);
for(i=1; i<=steps; i++) {
angle = (startAngle + i * angleStep) * twoPI;
xx = centerX + Math.cos(angle) * innerRadius;
yy = centerY + Math.sin(angle) * innerRadius;
drawObj.graphics.lineTo(xx,yy);
}
endAngle = startAngle + arcAngle;
for(i=0;i<=steps;i++) {
angle = (endAngle - i * angleStep) * twoPI;
xx = centerX + Math.cos(angle) * outerRadius;
yy = centerY + Math.sin(angle) * outerRadius;
drawObj.graphics.lineTo(xx,yy);
}
drawObj.graphics.lineTo(xxInit,yyInit);
};
var myArc:Shape = new Shape(); //or another DisplayObject
myArc.graphics.beginFill(0xcccccc, 0.50);
//objName, centerX,centerY, innerRadius, outerRadius, startAngle (12 o'clock is -90), arcAngle (degrees from startAngle), steps (smoothness)
drawSolidArc (myArc,250, 250, 180, 200, -90, 65, 100);
myArc.graphics.endFill();
this.addChild(myArc);
Upvotes: 3
Views: 3633
Reputation: 30158
I did something similar to Jeremy's solution, although I didn't mask it. Apparently if you create another arc of a smaller radius from the same center point, it will subtract from the existing shape, so I just made another call to drawSolidArc after the first, and before endFill, with zero as the centerpoint, and the outer radius being the desired inner radius of the first wedge:
var myArc:Sprite = new Sprite();
myArc.graphics.beginFill(0xcccccc, 1);
drawArc(myArc, 275, 200, 60, 150, 35); //spriteName, startX, startY, innerRadius, radius, arcAngle, startAngle
drawArc(myArc, 275, 200, 0, 60, 35); //subtract out the middle by drawing a new circle over the top of it
myArc.graphics.endFill();
this.addChild(myArc);
Upvotes: 1
Reputation: 14344
Below is a link to few different shape drawing classes I've written. You can achieve the desired segment of a circle by drawing a wedge and masking out the center of it with a second circle shape.
https://github.com/makemachine/makemachine.actionscript/tree/master/src/makemachine/display/shapes
Upvotes: 1
Reputation: 1350
Then there's this implementation. But it's almost as messy, as that which you've posted. I'm afraid there's no elegant way (few lines or so) of drawing an arc.
Upvotes: 0
Reputation: 5960
This is how I have done it:
Draw a doughnut and mask it:
_foreground = new Sprite();
_foreground.graphics.beginFill(_colour)
_foreground.graphics.drawCircle(0, 0, _outerRadius);
_foreground.graphics.drawCircle(0, 0, _innerRadius);
_foreground.graphics.endFill();
_container.addChild(_foreground);
_mask = new Sprite();
_mask.graphics.beginFill(0xff0000);
_foreground.mask = _mask;
Then draw it using this method - by drawing a wedge into the mask
private function draw(e:Event):void //Called each frame (if animating)
{
// No need to draw more than 360
if (Math.abs(_arc) > _endAngle)
{
_arc = _endAngle;
stop();
}
_numOfSegs = Math.ceil(Math.abs(_arc) / 45);
_segAngle = _arc / _numOfSegs;
_segAngle = (_segAngle / 180) * Math.PI;
_angle = (_startAngle / 180) * Math.PI;
// Calculate the start point
_ax = Math.cos(_angle) * _outerRadius;
_ay = Math.sin(-_angle) * _outerRadius;
// Draw the first line
_mask.graphics.lineTo(_ax, _ay);
for (var i:int=0; i<_numOfSegs; i++)
{
_angle += _segAngle;
_angleMid = _angle - (_segAngle / 2);
_bx = Math.cos(_angle) * _outerRadius;
_by = Math.sin(_angle) * _outerRadius;
_cx = Math.cos(_angleMid) * (_outerRadius / Math.cos(_segAngle / 2));
_cy = Math.sin(_angleMid) * (_outerRadius / Math.cos(_segAngle / 2));
_mask.graphics.curveTo(_cx, _cy, _bx, _by);
}
// Close the wedge
_mask.graphics.lineTo(0, 0);
_arc += 3.6; //This gives a 100 steps to complete the circle
}
Upvotes: 1
Reputation: 5978
Graphics.cubicCurveTo() will give you a better approximation of an arc than curveTo
. But it's still not perfect.
Upvotes: 1