使用 UIBezierPath 绘制圆弧段
Draw arc segments using UIBezierPath
我知道有很多与UIBezierPath
相关的例子,但是我对用来画弧的角度很困惑,我的要求就像image下面绘制弧线。长度和角度要按总数计算。
现在我已经创建了一个绘制弧线的函数,如下所示
-(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"];
}
我调用了上面的函数 3 次,所以它创建了 3 个弧段,如下所示
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"];
结果我得到如下输出
这在某种程度上是正确的,但不是 100%,如下场景
- 深灰色的起点与灰白色
的终点不同
- 深灰色部分应该始终半圈,蓝色应该紧随其后。
- off white段将剩余部分填到最后。
任何人都可以帮助我获得正确的值吗?以便绘制
谢谢。
更新(添加完整的解决方案来绘制相似的圆弧)
下面的函数负责为提供的角度绘制圆弧
-(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"];
}
下面的函数根据值计算角度并提供给上面的函数..
-(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];
}
希望对大家有所帮助。
问题是您使用整数表示角度,但处理的是弧度:
- (void)createCircleWithStartAngle:(int)startAngle endAngle:(int)endAngle name:(NSString *)name;
使用浮点数(例如 CGFloat
)作为角度。
我知道有很多与UIBezierPath
相关的例子,但是我对用来画弧的角度很困惑,我的要求就像image下面绘制弧线。长度和角度要按总数计算。
现在我已经创建了一个绘制弧线的函数,如下所示
-(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"];
}
我调用了上面的函数 3 次,所以它创建了 3 个弧段,如下所示
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"];
结果我得到如下输出
这在某种程度上是正确的,但不是 100%,如下场景
- 深灰色的起点与灰白色 的终点不同
- 深灰色部分应该始终半圈,蓝色应该紧随其后。
- off white段将剩余部分填到最后。
任何人都可以帮助我获得正确的值吗?以便绘制
谢谢。
更新(添加完整的解决方案来绘制相似的圆弧)
下面的函数负责为提供的角度绘制圆弧
-(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"];
}
下面的函数根据值计算角度并提供给上面的函数..
-(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];
}
希望对大家有所帮助。
问题是您使用整数表示角度,但处理的是弧度:
- (void)createCircleWithStartAngle:(int)startAngle endAngle:(int)endAngle name:(NSString *)name;
使用浮点数(例如 CGFloat
)作为角度。