ios开发之Quartz2D 四:画饼图

#import "PieView.h"

@implementation PieView



- (void)drawRect:(CGRect)rect {
    // Drawing code
    
    NSArray *dataArray = @[@25,@25,@50];
    CGPoint center =  CGPointMake(self.bounds.size.width * 0.5, self.bounds.size.height * 0.5);
    CGFloat radius = self.bounds.size.width * 0.5 - 10;
    CGFloat startA = 0;
    CGFloat angle = 0;
    CGFloat endA = 0;
    
    for (NSNumber *num in dataArray) {
        
        startA = endA;
        angle = num.intValue / 100.0 * M_PI * 2;
        endA = startA + angle;
        UIBezierPath  *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES];
        [[self randomColor] set];
        //添加一根线到圆心
        [path addLineToPoint:center];
        [path fill];
    }
    
}


-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    
    //重绘:1:drawRect方法不能手动去调用,否则不会自动生成与view有关的图形上下文 2:手动调用setNeedsDisplay,则系统会自动调用drawRect重绘,只要是系统自动调用的drawRect,都会自动生成与图形相关的上下文,fill,strokn都默认执行了绘图的几个步骤,要想实现绘图,需要自定义view,实现drawRect方法
    [self setNeedsDisplay];
}


//生成一个随机的颜色
- (UIColor *)randomColor {
    
    //arc4random_uniform:生成的随机数,范围为256,则生成的随机数范围是 0 -255
    CGFloat r = arc4random_uniform(256) / 255.0;
    CGFloat g = arc4random_uniform(256) / 255.0;
    CGFloat b = arc4random_uniform(256) / 255.0;
    
   return  [UIColor colorWithRed:r green:g blue:b alpha:1];
}





- (void)drawPie{
    //画第一个扇形
    CGPoint center =  CGPointMake(self.bounds.size.width * 0.5, self.bounds.size.height * 0.5);
    CGFloat radius = self.bounds.size.width * 0.5 - 10;
    CGFloat startA = 0;
    CGFloat angle = 25 / 100.0 * M_PI * 2;//当计算除法的时候,若是用浮点数CGFloat修饰,就要除以一个100.0,后面有小数
    CGFloat endA = startA + angle;
    
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES];
    
    [[UIColor redColor] set];
    //添加一根线到圆心
    [path addLineToPoint:center];
    [path fill];//调用的stroken描点或是fill填充都默认开启了图形上下文,绘制路径,把路径添加到图形上下文中,将图形上下文渲染到view上,其中调用fill,会自动添加一条线形成闭环
    
    //画第二个扇形
    
    startA = endA;
    angle = 25 / 100.0 * M_PI * 2;
    endA = startA + angle;
    path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES];
    [[UIColor greenColor] set];
    //添加一根线到圆心
    [path addLineToPoint:center];
    [path fill];
    
    
    startA = endA;
    angle = 50 / 100.0 * M_PI * 2;
    endA = startA + angle;
    path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:YES];
    [[UIColor blueColor] set];
    //添加一根线到圆心
    [path addLineToPoint:center];
    [path fill];

}


@end

  第一步, 获取上下文

        第二步,拼接路径 ,绘制第一个扇形

         获取上下文

         CGContextRef ctx =  UIGraphicsGetCurrentContext();

         CGPoint center = CGPointMake(125, 125);

         CGFloat radius = 100;

         CGFloat startA = 0;

         CGFloat endA = 0;

         CGFloat angle = 25 / 100.0 * M_PI * 2;

         endA = startA + angle;

         拼接路径

         UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center 

                       radius:radius 

                       startAngle:startA 

                       endAngle:endA 

                       clockwise:YES];

         添加一根线到圆心

         [path addLineToPoint:center];

         把路径添加到上下文

         CGContextAddPath(ctx, path.CGPath);

         把上下文渲染到View

         CGContextFillPath(ctx);

        

         注意点: CGFloat angle = 25 / 100.0 * M_PI * 2; 

                100.0一定要加一个.0

        绘制第二个扇形

        一样的, 把路径描述第二个扇形就好了

        直接来个path =

        让Path指针重新指向一个新的对象.也就是把指针重复利用了

        之前的那个对象已经用完了,已经添加到了上下文当中了.

         第二个扇形

         startA = endA;

         angle = 25 / 100.0 * M_PI * 2;

         endA = startA + angle;

         path = [UIBezierPath bezierPathWithArcCenter:center

          radius:radius 

          startAngle:startA 

          endAngle:endA 

          clockwise:YES];

         [path addLineToPoint:center];

         把二个路径添加到上下文

         CGContextAddPath(ctx, path.CGPath);

         把上下文渲染到View

         CGContextFillPath(ctx);

        添加第二个扇形之后, 发现它们的颜色都一样,想要修改它的颜色

        在下面再写一个

        [[UIColor greenColor] set];

        下面的一个颜色把之前的东西给覆盖了.

        解决办法, 让它渲染两次

        第三个扇形,把第二个拷贝一下就好了

        总结:

            有没有发现在画三个扇形用太多代码了,

            里面有很多代码相似.

            是不是可以把代码给抽一下

            可以用便利数组的的方式

            发现就两个地方变了, 一个数字变了, 一个颜色变了.

        抽取代码:

            假设他给一组数据

            NSArray datas =  @[@25,@25,@50];

            把数组便利出来

            

         NSArray *datas =  @[@25,@25,@50];

         

         CGPoint center = CGPointMake(125, 125);

         CGFloat radius = 100;

         CGFloat startA = 0;

         CGFloat angle = 0;

         CGFloat endA = 0;

         

         for (NSNumber *number in datas) {

         

         startA = endA;

         angle = number.intValue / 100.0 * M_PI * 2;

         endA = startA + angle;

         

         描述路径

         UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center 

           radius:radius

           startAngle:startA

           endAngle:endA

           clockwise:YES];

         

         [path addLineToPoint:center];

         [[self randomColor] set];

         [path fill];

         

         }

         - (UIColor *)randomColor{

         CGFloat r = arc4random_uniform(256)/ 255.0;

         CGFloat g = arc4random_uniform(256)/ 255.0;

         CGFloat b = arc4random_uniform(256)/ 255.0;

         return [UIColor colorWithRed:r green:g blue:b alpha:1];

         

         }

            

        随机颜色:alpha通道它的取值范围是0-255;

                OC里面的取值范围只能是0到1,把它 / 255.0就让它到这个范围了,

                arc4random_uniform(256)随机产生 0 - 255的数.

                颜色通道它的取值范围是0 到 255.

                所以说要把0 到 255转换成0 到 1

                直接是  0 ~ 255 / 255.0就可以了.

                刚好是255就是255 / 255.0 就是1,

                刚才是0 就是 0 / 255.0 就是0.

                

原文地址:https://www.cnblogs.com/cqb-learner/p/5820676.html