2010-09-16 27 views
25

Para una aplicación de iPhone, quiero dibujar un círculo, que es solo para un porcentaje x lleno.Dibuja parte de un círculo

Algo como esto:

alt text

no tengo problemas de cálculo del radio, los grados o los radianes, que no es ningún problema. También dibujar el círculo ya está hecho. Pero, ¿cómo obtengo el SDK de iPhone para dibujar la parte que está llena?

Puedo dibujar un rectángulo de ese tamaño, pero no forma parte de un círculo.

Solo quiero dibujar eso en un contexto normal.

Espero que alguien me puede dar algunos consejos aquí.

Respuesta

20

funciones de arco Uso CGContext 's:

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

consulte la documentación de CGContextAddArc().

+3

Eso es bastante fácil de arreglar. Simplemente agregue 'CGContextMoveToPoint (context, centerX, centerY);' en la línea anterior. –

8

Prueba esto:

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

he implementado una vista progreso pastel que tiene una apariencia similar a lo que está haciendo. Es de código abierto. Con suerte, el código fuente ayudará.

SSPieProgressView.h source

SSPieProgressView.m source

+0

¡Gracias por esto! Es la mejor respuesta para la publicación así que +1. Un código realmente agradable y sucinto. Realmente aprecio que lo hayas puesto en GitHub. ¡Gracias! –

45

Una gran cantidad de personas que han mostrado cómo se puede hacer esto en el núcleo gráfico sino que también se puede hacer con Core Animation que da la gran Además de ser fácilmente capaz de animar el porcentaje de la forma del pastel.

El siguiente código creará el anillo y las capas parcialmente llenas (aunque dijiste que ya puedes dibujar el anillo), ya que es bueno tener el anillo y la forma del pastel para dibujar utilizando el mismo método.

Si anima las propiedades strokeStart o de la capa pieShape, tendrá el porcentaje animado. Al igual que con todos los códigos Core Animation, necesitará agregar QuartzCore.framework a su proyecto e incluir <QuartzCore/QuartzCore.h> en su código.

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

Esta es una gran respuesta. – zekel

+1

Aquí hay una animación para este strokeStart (o puede usar 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

A continuación se muestra un método completo que estoy usando que hace esto con Core Graphics, adaptándose y expandiendo el comentario de mharper anterior.

Este código es para OSX Cocoa, pero podría cambiarse fácilmente a iOS, modificando cómo se obtiene el contexto.

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

probar este código en un UIView, Ejemplo "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); 

    } 
} 

Implementación en su 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]; 

Saludos.

1

Bueno, ya que nadie utiliza NSBezierPath hasta el momento, pensé que podría proporcionar la solución recientemente he usado para el mismo problema:

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

Nota: se puede utilizar uno de los métodos 2: "drawCircleWithCircleCenter" o "drawCircleWithCircleCenter2"

este código si tu hormiga para dividir la célula en 2 partes solamente

si desea dividir la célula en más de 2 partes se puede comprobar esto: "Drawing a circle ,filled different parts with different color" y comprobar la respuesta se inicia con esta frase "tenemos 6 clase"

Cuestiones relacionadas