画出一个圆圈的一部分

时间:2010-09-16 18:39:33

标签: iphone objective-c cocoa-touch

对于iPhone应用程序,我想绘制一个圆圈,仅用于填充x百分比。

这样的事情:

alt text

我没有问题计算半径,度数或弧度,这没有问题。绘制圆圈也已完成。但是如何让iPhone SDK绘制已填充的部分。

我可以画一个大小的矩形,但不是圆圈的一部分。

我只是想在正常的背景下绘制它。

希望有人能在这里给我任何指示。

8 个答案:

答案 0 :(得分:46)

很多人都向您展示了如何在Core Graphics中完成这项工作,但也可以使用Core Animation完成,这样可以轻松地为饼形的百分比设置动画。

以下代码将创建环和部分填充的图层(即使您说您已经可以绘制环),因为它很好地使用相同的方法绘制环和饼形状。 / p>

如果您为pieShape图层的strokeStartstrokeEnd属性设置动画,则您将获得百分比动画。与所有Core Animation代码一样,您需要将QuartzCore.framework添加到项目中,并在代码中包含<QuartzCore/QuartzCore.h>

// Create a white ring that fills the entire frame and is 2 points wide.
// Its frame is inset 1 point to fit for the 2 point stroke width
CGFloat radius = MIN(self.frame.size.width,self.frame.size.height)/2;
CGFloat inset  = 1;
CAShapeLayer *ring = [CAShapeLayer layer];
ring.path = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(self.bounds, inset, inset) 
                                       cornerRadius:radius-inset].CGPath;

ring.fillColor   = [UIColor clearColor].CGColor;
ring.strokeColor = [UIColor whiteColor].CGColor;
ring.lineWidth   = 2;

// Create a white pie-chart-like shape inside the white ring (above).
// The outside of the shape should be inside the ring, therefore the
// frame needs to be inset radius/2 (for its outside to be on 
// the outside of the ring) + 2 (to be 2 points in).
CAShapeLayer *pieShape = [CAShapeLayer layer];
inset = radius/2 + 2; // The inset is updated here
pieShape.path = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(self.bounds, inset, inset)
                                        cornerRadius:radius-inset].CGPath;
pieShape.fillColor   = [UIColor clearColor].CGColor;
pieShape.strokeColor = [UIColor whiteColor].CGColor;
pieShape.lineWidth   = (radius-inset)*2;   

// Add sublayers
// NOTE: the following code is used in a UIView subclass (thus self is a view)
// If you instead chose to use this code in a view controller you should instead
// use self.view.layer to access the view of your view controller.
[self.layer addSublayer:ring];
[self.layer addSublayer:pieShape];

答案 1 :(得分:20)

使用CGContext的弧函数:

CGContextAddArc(context,
                centerX,
                centerY,
                radius,
                startAngleRadians,
                endAngleRadians,
                clockwise ? 1 : 0);     

请参阅CGContextAddArc()的文档。

答案 2 :(得分:8)

试试这个:

CGContextMoveToPoint(the center point)
CGContextAddLineToPoint(the starting point of the fill path on the circumference)
CGContextAddArcToPoint(the ending point of the fill path on the circumference)
CGContextAddLineToPoint(the center point)
CGContextFillPath

答案 3 :(得分:6)

我实现了一个类似于你正在做的饼图进度视图。它是开源的。希望源代码能有所帮助。

SSPieProgressView.h source

SSPieProgressView.m source

答案 4 :(得分:2)

<强> CircleViewController.h

#import <UIKit/UIKit.h>

@interface CircleViewController : UIViewController

@end

<强> CircleViewController.m

#import "CircleViewController.h"
#import "GraphView.h"

@interface CircleViewController ()

@end

@implementation CircleViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    GraphView *graphView = [[GraphView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];
    graphView.backgroundColor = [UIColor whiteColor];
    graphView.layer.borderColor = [UIColor redColor].CGColor;
    graphView.layer.borderWidth = 1.0f;

    [self.view addSubview:graphView];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

<强> GraphView.h

#import <UIKit/UIKit.h>

@interface GraphView : UIView

@end

<强> GraphView.m

#import "GraphView.h"

@implementation GraphView

- (void)drawRect:(CGRect)rect {

    CGPoint circleCenter = CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2);

    [self drawCircleWithCircleCenter:(CGPoint) circleCenter radius:80 firstColor:[UIColor blueColor].CGColor secondeColor:[UIColor redColor].CGColor lineWidth:2 startDegree:0 currentDegree:90];
    //[self drawCircleWithCircleCenter2:(CGPoint) circleCenter radius:80 firstColor:[UIColor blueColor].CGColor secondeColor:[UIColor redColor].CGColor lineWidth:2 startDegree:0 currentDegree:90];
}

- (void)drawCircleWithCircleCenter:(CGPoint) circleCenter
                            radius:(CGFloat)radius
                            firstColor:(CGColorRef)firstColor
                            secondeColor:(CGColorRef)secondeColor
                            lineWidth:(CGFloat)lineWidth
                            startDegree:(float)startDegree
                            currentDegree:(float)endDegree {

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(context, lineWidth);

    CGContextMoveToPoint(context, circleCenter.x, circleCenter.y);

    CGContextAddArc(context, circleCenter.x , circleCenter.y, radius, [self radians:startDegree], [self radians:endDegree], 0);
    CGContextSetFillColorWithColor(context, firstColor);
    CGContextFillPath(context);

    CGContextMoveToPoint(context, circleCenter.x, circleCenter.y);

    CGContextAddArc(context, circleCenter.x, circleCenter.y, radius, [self radians:endDegree], [self radians:startDegree], 0);
    CGContextSetFillColorWithColor(context, secondeColor);
    CGContextFillPath(context);
}

- (void)drawCircleWithCircleCenter2:(CGPoint) circleCenter
                            radius:(CGFloat)radius
                        firstColor:(CGColorRef)firstColor
                      secondeColor:(CGColorRef)secondeColor
                         lineWidth:(CGFloat)lineWidth
                       startDegree:(float)startDegree
                     currentDegree:(float)endDegree {

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(context, lineWidth);

    CGContextMoveToPoint(context, circleCenter.x, circleCenter.y);

    CGContextAddArc(context, circleCenter.x , circleCenter.y, radius, [self radians:startDegree], [self radians:endDegree], 0);
    CGContextSetFillColorWithColor(context, firstColor);
    CGContextFillPath(context);

    CGContextMoveToPoint(context, circleCenter.x, circleCenter.y);

    CGContextAddArc(context, circleCenter.x, circleCenter.y, radius, [self radians:endDegree], [self radians:startDegree], 0);
    CGContextSetStrokeColorWithColor(context, secondeColor);
    CGContextStrokePath(context);
}

-(float) radians:(double) degrees {
    return degrees * M_PI / 180;
}


@end

注意:您可以使用以下两种方法之一: &#34; drawCircleWithCircleCenter&#34;或&#34; drawCircleWithCircleCenter2&#34;

此代码,如果您只想在2个部分上拆分

如果您想要分割超过2个部分的单元格,可以查看:&#34; Drawing a circle ,filled different parts with different color&#34;并从这个短语开始检查答案&#34;我们有6个课程&#34;

答案 5 :(得分:1)

好吧,因为到目前为止没有人使用NSBezierPath,我想我可以提供我最近用于同一问题的解决方案:

-(void)drawRect:(NSRect)dirtyRect
{
    double start = -10.0; //degrees
    double end = 190.0; //degrees
    NSPoint center = NSMakePoint(350, 200);
    double radius = 50;

    NSBezierPath *sector = [NSBezierPath bezierPath];
    [sector moveToPoint:center];
    [sector appendBezierPathWithArcWithCenter:center radius:radius startAngle:start endAngle:end];
    [sector lineToPoint:center];
    [sector fill];
}

答案 6 :(得分:0)

以下是我正在使用的一个完整方法,它使用Core Graphics,在上面的mharper评论中进行调整和扩展。

此代码适用于OSX Cocoa,但可以通过修改上下文的方式轻松更改为iOS。

- (void)drawPieShapedCircleWithRadius:(CGFloat)radius
                      strokeColor:(CGColorRef)strokeColor
                        fillColor:(CGColorRef)fillColor
                        lineWidth:(CGFloat)lineWidth
                   currentDegrees:(float)currentDegrees
                     startDegrees:(float)startDegrees {
    // get the context
    CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];

    // Set the color of the circle stroke and fill
    CGContextSetStrokeColorWithColor(context, strokeColor);
    CGContextSetFillColorWithColor(context, fillColor);

    // Set the line width of the circle
    CGContextSetLineWidth(context, 1);

    // Calculate the middle of the circle
    CGPoint circleCenter = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2);

    // Move the bezier to the center of the circle
    CGContextMoveToPoint(context, circleCenter.x, circleCenter.y);  // move to the center point

    // Draw the arc from the start point (hardcoded as the bottom of the circle) to the center
    CGContextAddLineToPoint(context, circleCenter.x, circleCenter.y + radius);

    // Draw the arc around the circle from the start degrees point to the current degrees point
    CGContextAddArc(context, circleCenter.x , circleCenter.y, radius, [self radians:startDegrees], [self radians:startDegrees + currentDegrees], 0);

    // Draw the line back into the center of the circle
    CGContextAddLineToPoint(context, circleCenter.x, circleCenter.y);

    // Fill the circle
    CGContextFillPath(context);

    // Draw the line around the circle
    CGContextStrokePath(context);
}

答案 7 :(得分:0)

在UIView中尝试此代码,示例&#34; MyChartClass&#34; ...

- (void)drawRect:(CGRect)rect {
    int c=(int)[itemArray count];

    CGFloat angleArray[c];
    CGFloat offset;
    int sum=0;

    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetAllowsAntialiasing(context, false);
    CGContextSetShouldAntialias(context, false);

    for(int i=0;i<[itemArray count];i++) {
        sum+=[[itemArray objectAtIndex:i] intValue];
    }

    for(int i=0;i<[itemArray count];i++) {
        angleArray[i]=(float)(([[itemArray objectAtIndex:i] intValue])/(float)sum)*(2*3.14); 
        CGContextMoveToPoint(context, radius, radius);
        if(i==0)
            CGContextAddArc(context, radius, radius, radius, 0,angleArray[i], 0);
        else
            CGContextAddArc(context, radius, radius, radius,offset,offset+angleArray[i], 0);
        offset+=angleArray[i];

        CGContextSetFillColorWithColor(context, ((UIColor *)[myColorArray objectAtIndex:i]).CGColor);
        CGContextClosePath(context); 
        CGContextFillPath(context);

    }   
}

在UIViewController中实现

MyChartClass *myChartClass=[[MyChartClass alloc]initWithFrame:CGRectMake(0, 0, 200, 200)];
myChartClass.backgroundColor = [UIColor clearColor];
myChartClass.itemArray=[[NSArray alloc]initWithObjects:@"75",@"25", nil];
myChartClass.myColorArray=[[NSArray alloc]initWithObjects:[UIColor blackColor],[UIColor whiteColor], nil];
myChartClass.radius=100;
[self.view addSubview:myChartClass];

问候。