iOS-弧形渐变进度条

弧形渐变效果图

iOS-弧形渐变进度条_第1张图片
IMG_0114.PNG-w150

CAShapeLayer

基本属性设置

CAShapeLayer *shapeLayer = [CAShapeLayer layer];
        shapeLayer.path = [UIBezierPath
                           bezierPathWithArcCenter:CGPointMake(self.frame.size.width * 0.5, self.frame.size.height * 0.5 + 110)
                           radius:120
                           startAngle:(150.f * M_PI) / 180.f
                           endAngle:(390.f * M_PI) / 180.f
                           clockwise:1].CGPath;
        shapeLayer.fillColor = [UIColor clearColor].CGColor;
        shapeLayer.strokeColor = [UIColor lightGrayColor].CGColor;
        shapeLayer.lineWidth = 15.f;
        shapeLayer.lineCap = kCALineCapRound;
        shapeLayer.opacity = 0.8;

属性介绍

strokeStart属性和strokeEnd属性

strokeStart和strokeEnd 是一个0-1的取值范围。表示一段路径的开始和结尾。比如开始位置为0.5,结束位置为1 ,那就只渲染出后半段的路径。
strokeStart 翻译过来就是清除开始位置。
strokeEnd 意思就是清除结束的位置。

  • keyPath = strokeStart 动画的fromValue = 0,toValue = 1:
    表示从路径的0位置画到1 怎么画是按照清除开始的位置也就是清除0 一直清除到1 效果就是一条路径慢慢的消失。
  • keyPath = strokeStart 动画的fromValue = 1,toValue = 0:
    表示从路径的1位置画到0 怎么画是按照清除开始的位置也就是1 这样开始的路径是空的(即都被清除掉了)一直清除到0 效果就是一条路径被反方向画出来。
  • keyPath = strokeEnd 动画的fromValue = 0,toValue = 1:
    表示 这里我们分3个点说明动画的顺序 strokeEnd从结尾开始清除 首先整条路径先清除后2/3,接着清除1/3 效果就是正方向画出路径。
  • keyPath = strokeEnd 动画的fromValue = 1,toValue = 0:
    效果就是反方向路径慢慢消失。

那么我们就可以利用strokeStart和strokeEnd这两个属性,对CAShapeLayer进行添加动画,在设置percent时,进度条就会出现增大,和减少的两种动态效果。

- (void)setPercent:(CGFloat)percent {
    _shapeLayer.path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.frame.size.width * 0.5, self.frame.size.height * 0.5 + 110) radius:120 startAngle:(150.f * M_PI) / 180.f endAngle:((240.f * (percent - 150.f) / 800.f + 150.f) * M_PI) / 180.f clockwise:1].CGPath;
    CGFloat value = (percent - 150.f) / 800.f;   //计算进度条的位置点
    _shapeLayer.strokeStart = MIN(0, value);
    _shapeLayer.strokeEnd = MAX(0, value);
}

CAGradientLayer

基本属性设置,并给CAShapeLayer添加渐变色。做成的整体的进度条效果。

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        CAShapeLayer *shapeLayer = [CAShapeLayer layer];
        shapeLayer.path = [UIBezierPath
                           bezierPathWithArcCenter:CGPointMake(self.frame.size.width * 0.5, self.frame.size.height * 0.5 + 110)
                           radius:120
                           startAngle:(150.f * M_PI) / 180.f
                           endAngle:(390.f * M_PI) / 180.f
                           clockwise:1].CGPath;
        shapeLayer.fillColor = [UIColor clearColor].CGColor;
        shapeLayer.strokeColor = [UIColor lightGrayColor].CGColor;
        shapeLayer.lineWidth = 15.f;
        shapeLayer.lineCap = kCALineCapRound;
        shapeLayer.opacity = 0.8;
        _shapeLayer = shapeLayer;
        //上方层
        CAGradientLayer *gradientLayer1 = [CAGradientLayer layer];
        gradientLayer1.frame = self.frame;
        gradientLayer1.colors = self.colorsTop;
        gradientLayer1.startPoint = CGPointMake(0, 0);
        gradientLayer1.endPoint = CGPointMake(1, 0);
        gradientLayer1.mask = shapeLayer;
        
        //左下层
        CAGradientLayer *gradientLayer2 = [CAGradientLayer layer];
        gradientLayer2.frame = CGRectMake(0, SHEIGHT / 2.f + circleRadius / 3.f , SWIDTH / 2, circleRadius * 1.3);
        gradientLayer2.colors = self.colorsLeftBottom;
        gradientLayer2.startPoint = CGPointMake(0, 1);
        gradientLayer2.endPoint = CGPointMake(0, 0);
        
        //右下层
        CAGradientLayer *gradientLayer3 = [CAGradientLayer layer];
        gradientLayer3.frame = CGRectMake(SWIDTH / 2, SHEIGHT / 2.f + circleRadius / 3.f , SWIDTH / 2, circleRadius * 1.3);
        gradientLayer3.colors = self.colorsRightBottom;
        gradientLayer3.startPoint = CGPointMake(0, 0);
        gradientLayer3.endPoint = CGPointMake(0, 1);
        
        [self.layer addSublayer:gradientLayer1];
        [gradientLayer1 addSublayer:gradientLayer2];
        [gradientLayer1 addSublayer:gradientLayer3];
        [gradientLayer1 setLocations:@[@0.35,@0.5,@0.75]];
        [gradientLayer3 setLocations:@[@0.2,@0.5,@0.75]];
        [gradientLayer2 setLocations:@[@0.2,@0.5,@0.75]];
    }
    return self;
}

- (NSMutableArray *)colorsTop {
    if (!_colorsTop) {
        _colorsTop = [NSMutableArray array];
        [_colorsTop addObject:(__bridge id)RGB(0xe2, 0xf2, 0x69).CGColor];
        [_colorsTop addObject:(__bridge id)RGB(0xff, 0xcf, 0x57).CGColor];
        [_colorsTop addObject:(__bridge id)RGB(0xff, 0xa8, 0x4c).CGColor];
    }
    return _colorsTop;
}

- (NSMutableArray *)colorsLeftBottom {
    if (!_colorsLeftBottom) {
        _colorsLeftBottom = [NSMutableArray array];
        [_colorsLeftBottom addObject:(__bridge id)RGB(0x73, 0xf2, 0x92).CGColor];
        [_colorsLeftBottom addObject:(__bridge id)RGB(0xab, 0xf2, 0x6e).CGColor];
        [_colorsLeftBottom addObject:(__bridge id)RGB(0xe2, 0xf2, 0x69).CGColor];
    }
    return _colorsLeftBottom;
}

- (NSMutableArray *)colorsRightBottom {
    if (!_colorsRightBottom) {
        _colorsRightBottom = [NSMutableArray array];
        [_colorsRightBottom addObject:(__bridge id)RGB(0xff, 0xa8, 0x4c).CGColor];
        [_colorsRightBottom addObject:(__bridge id)RGB(0xff, 0x80, 0x4c).CGColor];
        [_colorsRightBottom addObject:(__bridge id)RGB(0xe2, 0x56, 0x4c).CGColor];
    }
    return _colorsRightBottom;
}

- (void)setPercent:(CGFloat)percent {
//    _shapeLayer.path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.frame.size.width * 0.5, self.frame.size.height * 0.5 + 110) radius:120 startAngle:degreesToRadians(150.f) endAngle:degreesToRadians(percent / 200.f * 240.f + 150.f) clockwise:1].CGPath;
    CGFloat value = percent / 200.f;   //计算进度条的位置点
    _shapeLayer.strokeStart = MIN(0, value);
    _shapeLayer.strokeEnd = MAX(0, value);
}

关于CABasicAnimation,使用strokeStart和strokeEnd做动画时,可以不添加这个animation,也是有动画效果的,在进度条偶尔增大偶尔减少时我觉得用属性设置的方式比较好。
关于设置渐变色的位置,在未添加gradientLayer的mask的效果如图,这样可以更清楚的看到,三种颜色过渡方式,上方为从左向右进行过渡,左下方为从下到上进行过渡,右下方为从上到下进行过渡,看到整体效果后,再去添加mask,就可以实现一个平滑的弧形过渡啦。

iOS-弧形渐变进度条_第2张图片
IMG_0115.PNG

你可能感兴趣的:(iOS-弧形渐变进度条)