2010-09-16 15 views
25

W przypadku aplikacji na iPhone'a chcę narysować okrąg, czyli tylko dla wypełnionego procentu x.Narysuj część okręgu

coś takiego:

alt text

mam żadnych problemów obliczanie promienia stopni ani radiany, że nie jest problemem. Również rysunek koła jest już gotowy. Ale jak uzyskać zestaw SDK iPhone'a do narysowania części, która jest wypełniona.

Mogę narysować prostokąt o takim rozmiarze, ale nie będący częścią okręgu.

Po prostu chcę narysować to w normalnym kontekście.

Mam nadzieję, że ktoś może podać mi jakieś wskazówki.

Odpowiedz

20

Zastosowanie CGContext „s funkcje arc:

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

zapoznać się z dokumentacją CGContextAddArc().

+3

Jest to dość łatwe do naprawienia. Wystarczy dodać 'CGContextMoveToPoint (context, centerX, centerY);' w linii wcześniej. –

8

Spróbuj tego:

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

I wdrożone pie widok postępu, który wygląda podobnie do tego, co robisz. To jest open source. Mam nadzieję, że kod źródłowy pomoże.

SSPieProgressView.h source

SSPieProgressView.m source

+0

Dzięki za to! To najlepsza odpowiedź na pocztę, więc +1. Naprawdę ładny, zwięzły kod. Naprawdę doceniam, że umieściłeś go na GitHub. Dzięki! –

45

Wiele osób wykazały, w jaki sposób można to zrobić w rdzeń graficzny, ale to może być również wykonane z Core Animation, który daje duży dodatek łatwo jest w stanie ożywić procent kształtu ciasta.

Poniższy kod spowoduje utworzenie zarówno pierścienia, jak i częściowo wypełnionych warstw (nawet jeśli powiedziałeś, że możesz już narysować pierścień), ponieważ dobrze jest mieć zarówno pierścień, jak i kształt koła do rysowania przy użyciu tej samej metody.

Jeśli animujesz właściwości strokeStart lub strokeEnd warstwy pieShape, procent będzie animowany. Podobnie jak w przypadku całego kodu Core Animation, musisz dodać QuartzCore.framework do swojego projektu i dołączyć do kodu kod <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]; 
+4

To jest świetna odpowiedź. – zekel

+1

Oto animacja dla tego strokeStart (lub można użyć strokeEnd): 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

Poniżej znajduje się pełna metoda używam, że robi to z rdzenia graficznego, adaptacji i rozbudowy na komentarzu mharper za wyżej.

Ten kod jest przeznaczony dla systemu OSX Cocoa, ale można go łatwo zmienić na system iOS, modyfikując sposób uzyskiwania kontekstu.

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

Spróbuj tego kodu w UIView, przykład "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); 

    } 
} 

Wdrożenie w 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]; 

Pozdrawiam.

1

cóż, skoro nikt do tej pory wykorzystywane NSBezierPath, wyobraziłem mogę dostarczyć rozwiązanie Niedawno wykorzystywane do tego samego problemu:

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

UWAGA: Można zastosować jedną z metod 2: "drawCircleWithCircleCenter" lub "drawCircleWithCircleCenter2"

ten kod, jeśli w mrówka podzielić komórkę na 2 części tylko

jeśli chcesz podzielić komórkę na więcej niż 2 części można sprawdzić w ten sposób: „Drawing a circle ,filled different parts with different color” i sprawdzić odpowiedź zacząć tę frazę „mamy 6 klasę”