iOS-弧形渐变进度条
2017-09-01 本文已影响121人
rapunzelyeah
弧形渐变效果图
IMG_0114.PNG-w150CAShapeLayer
基本属性设置
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,就可以实现一个平滑的弧形过渡啦。