使用UIBezierPath绘制弧形线段

8

我知道有很多与UIBezierPath相关的示例,但是我对绘制弧线所需使用的角度感到非常困惑,我的要求如下图所示。长度和角度应根据总数计算。

enter image description here

现在,我已经创建了一个绘制弧线的函数,请参见下面的代码:

-(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"];

作为结果,我得到了如下输出: enter image description here 这个结果在某种程度上是正确的,但不是100%的,情况如下:
1. 起点(深灰色)与终点(浅灰色)不同。 2. 深灰色部分应始终为半圆形,蓝色应按比例跟随它。 3. 浅灰色段填充其余部分直至结束。
有人能帮我把数值弄对吗?这样就可以画出来了。
谢谢。
更新(添加绘制类似圆弧的完整解决方案):
下面的函数负责绘制提供的角度的圆弧。
-(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];

}

希望能对某些人有所帮助。


嗨,这是什么意思?“float factor=total/bvalue;”你能告诉我吗?另外,我使用了CGFloat,但圆形没有完全完成。它看起来像你上面展示的那样。 - Sagar Sukode
@SagarSukode 不用管那个问题的部分,我已经根据我和Rob的讨论更新了完整的解决方案,请重新加载并检查我的解决方案,它一定会帮助你解决类似的问题。 - iphonic
1个回答

5
问题在于您使用整数表示角度,但您正在处理弧度:
- (void)createCircleWithStartAngle:(int)startAngle endAngle:(int)endAngle name:(NSString *)name;

使用浮点数(例如 CGFloat)表示你的角度。


我多愚蠢啊,是的,现在我把它改成浮点数后绘图正确了。你能帮我调整角度因子吗? - iphonic
我有三个值A、B、C。例如:A=100,B=25,C=75。 A=深灰色,绘制到角度270B=一部分蓝色的A,从角度270开始绘制,B的结束角度根据A的值计算。而C是在B结束后绘制,直到角度60。因此,我需要计算B的结束角度。 - iphonic
因此,从270度到60度的角度将与B和C的分布值一起分配。 - iphonic
@iphonic - 让我们在聊天室里继续这个讨论 - Rob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接