简体   繁体   English

画圆的一部分

[英]Draw part of a circle

For an iPhone application I want to draw a circle, that is only for an x percentage filled. 对于iPhone应用程序,我想绘制一个圆圈,该圆圈仅适用于填充的x百分比。

Something like this: 像这样:

替代文字

I have no problems calculating the radius, the degrees or the radians, that is no problem. 我在计算半径,度数或弧度方面没有问题,这是没有问题的。 Also drawing the circle is already done. 绘制圆也已经完成。 But how do I get the iPhone SDK to draw the part that is filled. 但是我如何获得iPhone SDK来绘制填充的零件。

I can draw a rectangle that size, but not part of a circle. 我可以画一个矩形,但是大小不是圆的一部分。

I just want to draw that on aa normal context. 我只是想在正常情况下得出这一结论。

Hope someone can give me any pointers here. 希望有人可以在这里给我任何指示。

A lot of people have showed you how this can be done in Core Graphics but it can also be done with Core Animation which gives the big addition of easily being able to animate the percentage of the pie shape. 许多人向您展示了如何在Core Graphics中完成此操作,但也可以通过Core Animation完成,这大大增加了轻松制作饼形百分比动画的可能性。

The following code will create both the ring and the partly filled layers (even though you said that you already can draw the ring) since its nice to have both the ring and the pie shape to be drawn using the same method. 下面的代码将同时创建圆环和部分填充的图层(即使您已经说过可以绘制圆环),因为使用相同的方法绘制圆环和饼图形状很不错。

If you animate the strokeStart or strokeEnd properties of the pieShape layer you will have the percentage animate. 如果为pieShape图层的strokeStartstrokeEnd属性设置动画, 则将设置动画百分比。 As with all Core Animation code you will need to add QuartzCore.framework to your project and include <QuartzCore/QuartzCore.h> in your code. 与所有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];

Use CGContext 's arc functions: 使用CGContext的arc函数:

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

See the documentation for CGContextAddArc() . 请参阅CGContextAddArc()的文档。

Try this: 尝试这个:

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

I implemented a pie progress view that looks similar to what you are doing. 我实现了一个饼状进度视图,该视图与您正在执行的操作类似。 It's open source. 它是开源的。 Hopefully the source code will help. 希望源代码会有所帮助。

SSPieProgressView.h source SSPieProgressView.h源

SSPieProgressView.m source SSPieProgressView.m源

CircleViewController.h CircleViewController.h

#import <UIKit/UIKit.h>

@interface CircleViewController : UIViewController

@end

CircleViewController.m 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 GraphView.h

#import <UIKit/UIKit.h>

@interface GraphView : UIView

@end

GraphView.m 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

note: you can use one of the 2 methods: "drawCircleWithCircleCenter" or "drawCircleWithCircleCenter2" 注意:您可以使用以下两种方法之一:“ drawCircleWithCircleCenter”或“ drawCircleWithCircleCenter2”

this code if you want to split cell on 2 parts only 如果您只想将单元格拆分为2部分,则此代码

if you want to split cell on more than 2 parts you can check this : " Drawing a circle ,filled different parts with different color " and check the answer start with this Phrase "we have 6 class" 如果您想将单元格拆分为两个以上的部分,则可以检查以下内容:“ 画一个圆,用不同的颜色填充不同的部分 ”,并从此短语“我们有6类”开始检查答案

Well, since nobody used NSBezierPath so far, I figured I could provide the solution I recently used for the same problem: 好吧,由于到目前为止还没有人使用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];
}

Below is a full method I am using that does this with Core Graphics, adapting and expanding on mharper's comment above. 下面是我正在使用的完整方法,该方法可通过Core Graphics完成此操作,以适应和扩展mharper的上述评论。

This code is for OSX Cocoa, but could easily be changed to iOS, by modifying how you get the context. 该代码适用于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);
}

Try this code in a UIView, Example "MyChartClass"... 在UIView中尝试此代码,例如“ MyChartClass” ...

- (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);

    }   
}

Implementation in your UIViewController 在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];

Regards. 问候。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM