·您现在的位置: 云翼网络 >> 文章中心 >> 网站建设 >> app软件开发 >> IOS开发 >> 关情纸尾-----Quartz2D-绘制圆形下载进度条,饼图

关情纸尾-----Quartz2D-绘制圆形下载进度条,饼图

作者:佚名      IOS开发编辑:admin      更新时间:2022-07-23

绘制下载进度条

1.搭建界面.

2.拖动滑竿的时候让他里面的能够跟着我的拖动,数字在改变.
  数字改变时有一个注意点, 就是要显示%,它是一个特殊的符号,要用两个%%代表一个%

3.拖动滑竿的时候就是在上面画弧.
  从最上面,按顺时针画,所以,它的起始角度是-90度.结束角度也是-90度
  也是从起始角度开始画,
  起始角度-90度, 看你下载进度是多少
  假如说你下载进度是100,就是1 * 360度
  也就是说这个进度占你360度多少分之一

  CGContextRef ctx = UIGraphicsGetCurrentContext();
  CGPoint center = CGPointMake(50, 50);
  CGFloat radius = rect.size.width * 0.5;
  CGFloat startA = -M_PI_2;
  CGFloat endA = -M_PI_2 + M_PI * 2 * PRogress;

  UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center 
                              radius:radius 
                            startAngle:startA 
                             endAngle:endA 
                             clockwise:YES];

  要获得Progress的值,这个进度值没有, 所以要传进来才能画.弄一个成员变量
  要在值改变的时候就要传进来.
  要拿到ProgressView才能够传进来,所以要拖线,拿到ProgressView
  所有都做好的, 发现没有画圆孤?
  为什么?
  问题:drawRect方法总共调用多少次?
  总共就调用一次, 第一次Progress为0,以后都不会执行了
  解决:每次传的时候,就要画一次,
  重写Progress方法
  

-(void)setProgress:(CGFloat)progress{
    _progress = progress;  
    //手动调用drawRect方法, 让它重新绘制
    [self setNeedsDisplay];
}

  

 运行发现还是不画,为什么?

    原因:drawRect方法是不能手动调用,因为在drawRect方法中才能获取跟View相关联的上下文
    系统在调用DrawRect方法时,会自动帮你创建一个跟View相关联的上下文,并且传递给它.
    自己调用的,没有给drawRect方法传递上下文.所以在draw方法中拿不到上下文.

    解决办法:想要重绘,调用[self setNeedsDisplay];
    告诉系统重新绘制View,系统就会自动帮你调用drawRect方法,系统在调用
    drawRect方法,它会帮你创建上下文

 

绘制饼图

第一步, 获取上下文
第二步,拼接路径 ,绘制第一个扇形
获取上下文

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.