I know there are lots of example related to UIBezierPath
, but I am very confused about the angles to use to draw arc, my requirement is like the image below to draw arcs. The length and angle should be calculated as per total number.
Right now I have created a function which draws the arcs see below
-(void)createCircleWithStartAngle:(int)startAngle endAngle:(int)endAngle name:(NSString *)name{
UIView *subView=_viewContainer;
// Set up the shape of the circle
int radius = 125;
CAShapeLayer *circle = [CAShapeLayer layer];
// Make a circular shape
UIBezierPath *path=[UIBezierPath bezierPathWithArcCenter:CGPointMake(radius, radius) radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES];
circle.path = [path CGPath];
// Center the shape in self.view
circle.position = CGPointMake(CGRectGetMidX(subView.bounds)-radius,
CGRectGetMidY(subView.bounds)-radius);
circle.fillColor = [UIColor clearColor].CGColor;
//making line end cap round
circle.lineCap=kCALineCapRound;
UIColor *strokeColor;
if([name isEqualToString:@"A"])
strokeColor=[UIColor darkGrayColor];
else if([name isEqualToString:@"B"])
strokeColor=[UIColor colorWithRed:40.0/255.0 green:180.0/255.0 blue:213.0/255.0 alpha:1.0];
else if([name isEqualToString:@"C"])
strokeColor=[UIColor colorWithRed:240/255.0 green:240/255.0 blue:240/255.0 alpha:1.0];
circle.strokeColor = strokeColor.CGColor;
circle.lineWidth = 10;
// Add to parent layer
[subView.layer addSublayer:circle];
// Configure animation
CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
drawAnimation.duration = 1.0;
drawAnimation.repeatCount = 1.0;
drawAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
drawAnimation.toValue = [NSNumber numberWithFloat:1.0f];
drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
// Add the animation to the circle
[circle addAnimation:drawAnimation forKey:@"drawCircleAnimation"];
}
I am calling the above function 3 times so it creates 3 arc segments like below
float angleToStart=DEGREES_TO_RADIANS(120);
float angleToEnd=DEGREES_TO_RADIANS(270);
//investment
[self createCircleWithStartAngle:angleToStart endAngle:angleToEnd name:@"A"];
float factor=total/bvalue;
angleToStart=angleToEnd;
angleToEnd=180/factor;
angleToEnd=DEGREES_TO_RADIANS(angleToEnd);
[self createCircleWithStartAngle:angleToStart endAngle:angleToEnd name:@"B"];
angleToStart=DEGREES_TO_RADIANS(angleToEnd);
angleToEnd=DEGREES_TO_RADIANS(60);
[self createCircleWithStartAngle:angleToStart endAngle:angleToEnd name:@"C"];
as a result I am getting output like below
which is somehow correct, but not 100%, scenarios as below
Can anyone help me to get the values correct? So that it draws
Thanks.
Update(Adding complete solution to draw similar arc)
The function below responsible for drawing the arc for supplied angles
-(void)createCircleWithStartAngle:(float)startAngle endAngle:(float)endAngle chartSection:(ChartSection)section lineCap:(NSString *const)lineCap{
UIView *subView=_circleView;
// Set up the shape of the circle
float radius = _circleView.bounds.size.width/2.0;//125.0;
CAShapeLayer *circle = [CAShapeLayer layer];
// Make a circular shape
UIBezierPath *path=[UIBezierPath bezierPathWithArcCenter:CGPointMake(radius, radius) radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES];
circle.path = [path CGPath];
// Center the shape in self.view
circle.position = CGPointMake(CGRectGetMidX(subView.bounds)-radius,
CGRectGetMidY(subView.bounds)-radius);
// Configure the apperence of the circle
circle.fillColor = [UIColor clearColor].CGColor;
UIColor *strokeColor;
circle.lineCap=lineCap;
switch (section) {
case ChartSectionA:
strokeColor=[UIColor darkGrayColor];
break;
case ChartSectionB:
strokeColor=[UIColor colorWithRed:40.0/255.0 green:180.0/255.0 blue:213.0/255.0 alpha:1.0];
break;
case ChartSectionC:
strokeColor=[UIColor colorWithRed:240/255.0 green:240/255.0 blue:240/255.0 alpha:1.0];
break;
default:
strokeColor=[UIColor colorWithRed:40.0/255.0 green:180.0/255.0 blue:213.0/255.0 alpha:1.0];
break;
}
circle.strokeColor = strokeColor.CGColor;
circle.lineWidth = 10;
//keep the arrangement intact with the indexes..
[subView.layer insertSublayer:circle atIndex:section];
// Configure animation
CABasicAnimation *drawAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
drawAnimation.duration = 1.0;
drawAnimation.repeatCount = 1.0;
// Animate from no part of the stroke being drawn to the entire stroke being drawn
drawAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
drawAnimation.toValue = [NSNumber numberWithFloat:1.0f];
// Experiment with timing to get the appearence to look the way you want
drawAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
// Add the animation to the circle
[circle addAnimation:drawAnimation forKey:@"drawCircleAnimation"];
}
The function below calculates angle as per values and supplies to the function above..
-(void)createArcWithValueOfSectionA:(float)amountA sectionB:(float)amountB sectionC:(float)amountC{
if(amountA<0.0)
amountA=0.0;
if(amountB<0.0)
amountB=0.0;
if(amountC<0.0)
amountC=0.0;
float baseStartAngle=120.0;//base start angle
float baseEndAngle=60.0;//base end angle
float totalAngle=300.0;//total angle to be calculated
float sectionAPercent = amountA/(amountA+amountB+amountC);
float sectionBPercent = amountB/(amountA+amountB+amountC);
float angleToStart=DEGREES_TO_RADIANS(baseStartAngle);
float angleToEnd=0.0;
if(sectionAPercent<0)
sectionAPercent=0.0;
if(sectionBPercent<0)
sectionBPercent=0.0;
//calculate sectionA end angle with the value inputted
angleToEnd=baseStartAngle + sectionAPercent * totalAngle;
//we need to determine cap style as per data
NSString *lineCap=kCALineCapRound;
//Section A
[self createCircleWithStartAngle:angleToStart endAngle:DEGREES_TO_RADIANS(angleToEnd) chartSection:ChartSectionA lineCap:lineCap];
//next drawing for bidding should start from investment end angle
angleToStart=angleToEnd;
angleToEnd=sectionBPercent * totalAngle;
angleToEnd=angleToStart+angleToEnd;
lineCap=kCALineCapSquare;
//Section B
[self createCircleWithStartAngle:DEGREES_TO_RADIANS(angleToStart) endAngle:DEGREES_TO_RADIANS(angleToEnd) chartSection:ChartSectionB lineCap:lineCap];
//next drawing for sectionC should start from sectionB end angle
angleToStart=angleToEnd;
lineCap=kCALineCapRound;
//draw Section C amount till end
angleToEnd=DEGREES_TO_RADIANS(baseEndAngle);
[self createCircleWithStartAngle:DEGREES_TO_RADIANS(angleToStart) endAngle:angleToEnd chartSection:ChartSectionC lineCap:lineCap];
}
The problem is that you're using integers for your angles, but you're dealing with radians:
- (void)createCircleWithStartAngle:(int)startAngle endAngle:(int)endAngle name:(NSString *)name;
Use floating point (e.g. CGFloat
) for your angles.