绘图-圆环进度条实现详解

前言

实现了一款时下比较流行的环状进度动图,以下是源码解析


使用 Core Graphics 和 定时器 实现环形进度动图

绘图-圆环进度条实现详解_第1张图片
圆环进度.gif

核心源码

# 使用  [self setNeedsDisplay];  会触发drawRect 方法达到刷新视图的效果。
//画背景线、填充线、小圆点、文字
- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];
    
    
    #获取图形上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    
    #设置中心点 半径 起点及终点
    CGFloat maxWidth = self.frame.size.width

小球图片的坐标计算参照以下这张图

绘图-圆环进度条实现详解_第2张图片
Paste_Image.png

#设置进度 属性的 set 方法
- (void)setProgress:(CGFloat)progress {
    
    _progress = progress;
    fakeProgress = 0.0;
    
    if (timer) {
        [timer invalidate];
        timer = nil;
    }
    
    //如果为0则直接刷新
    if (_progress == 0.0) {
        [self setNeedsDisplay];
        return;
    }
    #生成一个定时器 持续触发  drawRect 方法
    timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(asa ) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    
}
#定时器绑定的方法
- (void)asa
{
    if (fakeProgress >= _progress || fakeProgress >= 1.0f) {
        #最后一次赋准确值 并移除定时器
        fakeProgress = _progress;
        [self setNeedsDisplay];
        
        if (timer) {
            [timer invalidate];
            timer = nil;
        }
        return;
    } else {
        #进度条动画
        [self setNeedsDisplay];
    }
    
    # fakeProgress 数值增加
    if (_animationModel == CircleIncreaseSameTime) {
        fakeProgress += 0.01*(_progress);//不同进度动画时间基本相同
    } else {
        fakeProgress += 0.01;//进度越大动画时间越长。
    }
}

使用 CAShapeLayer 和 CABasicAnimation 实现环形进度动图



绘图-圆环进度条实现详解_第3张图片
进度.gif

核心源码

# 橘红色的背景
CAShapeLayer *shapeLayer11=[CAShapeLayer layer];
UIBezierPath*path12=[UIBezierPath bezierPathWithOvalInRect:CGRectMake(89, 299, 138, 138)];
# 设置末端的形状为圆形
path12.lineCapStyle = kCGLineCapRound;  
shapeLayer11.path=path12.CGPath;
# 就是图中我们看到的橘红色   CAShapeLayer的fillColor 填充的是 贝塞尔曲线的有效区域   半径为 138的圆
shapeLayer11.fillColor=[UIColor colorWithRed:0.95 green:0.37 blue:0.38 alpha:1.00].CGColor;
# 设置lineWidth 为0
shapeLayer11.lineWidth=0;
 # lineWidth 为0 strokeColor没有效果
//shapeLayer11.strokeColor=[UIColor colorWithRed:0.95 green:0.37 blue:0.38 alpha:1.00].CGColor;
[self.layer addSublayer:shapeLayer11];

# 深绿色的区域
CAShapeLayer *shapeLayer1 = [CAShapeLayer layer];
UIBezierPath *path1 = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(89, 299, 138, 138)];
path1.lineCapStyle = kCGLineJoinRound;
shapeLayer1.path = path1.CGPath;
# 设置内部填充色为 无色
shapeLayer1.fillColor = [UIColor clearColor].CGColor; 
# 设计 lineWidth 为20 (深绿色区域)我们可以看到是绿色区域的中心线在贝塞尔曲线的边界上
shapeLayer1.lineWidth = 20;
shapeLayer1.strokeColor = [UIColor colorWithRed:0.16 green:0.58 blue:0.22 alpha:1.00].CGColor;
[self.layer addSublayer:shapeLayer1];

# strokeEnd为CAShapeLayer的终点,这里设置为动画的 KEY
CABasicAnimation *pathAnima = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
pathAnima.duration = 1.5f;
pathAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
pathAnima.fromValue = [NSNumber numberWithFloat:0.0f]; 
# 终点值设置为 0.8 
pathAnima.toValue = [NSNumber numberWithFloat:.8f];
pathAnima.fillMode = kCAFillModeForwards;
pathAnima.removedOnCompletion = NO;
[shapeLayer1 addAnimation:pathAnima forKey:nil];

你可能感兴趣的:(绘图-圆环进度条实现详解)