Draw arc segments using UIBezierPath

I know that there are many examples related to UIBezierPath , but I am very confused about the angles for drawing an arc, my requirement is similar to the image below for drawing arcs. Length and angle should be calculated as a total number.

enter image description here

Right now I created a function that draws arcs 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 call the above function 3 times, so it creates 3 arc segments as 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 get the output as shown below

enter image description here

which is somehow correct, but not 100%, the scripts below

  • The starting point of the dark gray is not the same as the ending point off white
  • Part of the dark gray should always be surrounded by half, and the blue should follow it with a factor.
  • The off white segment to fill the rest to the end.

Can someone help me get the correct values? So that he draws

Thanks.


Update (adding a complete solution for drawing a similar arc)

The function below is responsible for drawing an arc for given 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 the angle according to the values โ€‹โ€‹and supplies it 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]; } 

Hope this helps someone.

+7
ios objective-c geometry calayer uibezierpath
source share
1 answer

The problem is that you use integers for your angles, but you are dealing with radians:

 - (void)createCircleWithStartAngle:(int)startAngle endAngle:(int)endAngle name:(NSString *)name; 

Use floating points (e.g. CGFloat ) for your angles.

+4
source share

All Articles