2010-09-16 12 views
25

Für eine iPhone Anwendung möchte ich einen Kreis zeichnen, der nur für einen x Prozentsatz ausgefüllt ist.Zeichne einen Teil eines Kreises

Etwas wie folgt aus:

alt text

Ich habe keine Probleme mit dem Radius der Berechnung der Grad oder die Radiant, das ist kein Problem. Auch das Zeichnen des Kreises ist bereits erledigt. Aber wie bekomme ich das iPhone SDK, um den Teil zu zeichnen, der gefüllt ist.

Ich kann ein Rechteck dieser Größe zeichnen, aber nicht Teil eines Kreises.

Ich möchte nur auf einen normalen Kontext zeichnen.

Hoffe jemand kann mir hier irgendwelche Hinweise geben.

Antwort

20

Verwenden CGContext ‚s Bogen Funktionen:

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

finden Sie in der Dokumentation für CGContextAddArc().

+3

Das ist ziemlich einfach zu beheben. Fügen Sie einfach 'CGContextMoveToPoint (context, centerX, centerY);' in der Zeile davor hinzu. –

8

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 
6

ich implementiert eine Torte Fortschritt Ansicht, die ähnlich sieht, was man tut. Es ist Open Source. Hoffentlich hilft der Quellcode.

SSPieProgressView.h source

SSPieProgressView.m source

+0

Danke dafür! Es ist die beste Antwort auf die Post, also +1. Wirklich schöner, prägnanter Code. Schätze wirklich, dass du es auf GitHub gesetzt hast. Vielen Dank! –

45

Viele Leute haben Sie gezeigt, wie man dies in Core Graphics getan werden kann, aber es kann auch mit Core Animation getan werden, die die große Zugabe leicht in der Lage, geben die zu animieren Prozentsatz der Kuchenform.

Der folgende Code wird sowohl die Ring- als auch die teilweise gefüllten Layer erstellen (obwohl Sie bereits angegeben haben, dass Sie den Ring zeichnen können), da sowohl der Ring als auch die Kreisform mit der gleichen Methode gezeichnet werden können. Wenn Sie die Eigenschaften strokeStart oder strokeEnd der pieShape-Ebene animieren, wird der Prozentsatz animiert. Wie bei allen Core Animation-Codes müssen Sie Ihrem Projekt QuartzCore.framework hinzufügen und in Ihren Code einfügen.

// 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]; 
+4

Dies ist eine großartige Antwort. – zekel

+1

Hier ist eine Animation für diesen strokeStart (oder Sie können strokeEnd verwenden): CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; pathAnimation.duration = 3.0; pathAnimation.fromValue = [NSNumber numberWithFloat:0.0f]; pathAnimation.toValue = [NSNumber numberWithFloat:0.3f]; pathAnimation.removedOnCompletion = NO; pathAnimation.fillMode = kCAFillModeForwards; [pieShape addAnimation:pathAnimation forKey:@"strokeEndAnimation"]; cynistersix

0

Unten ist eine vollständige Methode, die ich verwende, die dies mit Core Graphics tut, Anpassung und Erweiterung auf Mharper Kommentar oben.

Dieser Code ist für OSX Cocoa, könnte aber leicht in iOS geändert werden, indem Sie den Kontext ändern.

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

Versuchen Sie diesen Code in einem UIView, Beispiel "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); 

    } 
} 

Implementierung in Ihrem 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]; 

Grüße.

1

Nun, da niemand NSBezierPath bisher verwendet, dachte ich, ich die Lösung bieten konnte ich vor kurzem für das gleiche Problem verwendet:

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

Anmerkung: Sie eines der zwei Methoden verwenden: "drawCircleWithCircleCenter" oder "drawCircleWithCircleCenter2"

Dieser Code wenn Sie w ant Zelle auf 2 Teile aufzuspalten nur

, wenn Sie Zelle geteilt werden soll auf mehr als 2 Teile prüfen Sie dies: „Drawing a circle ,filled different parts with different color“ und überprüfen Sie die Antwort mit diesem Satz beginnen: „Wir haben 6 Klasse“

Verwandte Themen