之前项目中,UI设计师要求金融理财模块做成如下效果图:
其中有涉及相应的动画 比如类似进度条图层颜色渐变动画,现将实现记录如下:
图层颜色渐变主要通过CAGradientLayer这个类进行实现
自定义一个控制器用来展示图层渐变动画
在此控制器中声明如下属性
//开启动画
@property (nonatomic,strong) UIButton *startAnimationBtn;
//显示动画的View
@property (nonatomic,strong) UIView *animationView;
//渐变图层
@property (nonatomic,strong) CALayer *gradientLayer;
//轨迹图层
@property (nonatomic,strong) CAShapeLayer *progressLayer;
gradientLayer 懒加载实现代码如下:
- (CALayer *)gradientLayer {
if (!_gradientLayer) {
_gradientLayer = [CALayer layer];
_gradientLayer.frame = CGRectMake(0, 0, kWidth, kHeight);
CAGradientLayer *gradientLayer1 = [CAGradientLayer layer];
gradientLayer1.frame = CGRectMake(0, 0, kWidth/2, kHeight);
[gradientLayer1 setColors:[NSArray arrayWithObjects:(id)[UIColor colorFromHexString:@"#2d75f0"].CGColor,(id)[UIColor colorFromHexString:@"#4888f2"].CGColor, nil]];
//渐变方向 从下往上
[gradientLayer1 setStartPoint:CGPointMake(0.5, 1)];
[gradientLayer1 setEndPoint:CGPointMake(0.5, 0)];
[_gradientLayer addSublayer:gradientLayer1];
CAGradientLayer *gradientLayer2 = [CAGradientLayer layer];
gradientLayer2.frame = CGRectMake(kWidth/2, 0, kWidth/2, kHeight);
[gradientLayer2 setColors:[NSArray arrayWithObjects:(id)[UIColor colorFromHexString:@"#4888f2"].CGColor,(id)[UIColor colorFromHexString:@"#46ddef"].CGColor, nil]];
//渐变方向 从上往下
[gradientLayer2 setStartPoint:CGPointMake(0.5, 0)];
[gradientLayer2 setEndPoint:CGPointMake(0.5, 1)];
[_gradientLayer addSublayer:gradientLayer2];
//用progressLayer来截取渐变层
// [_gradientLayer setMask:self.progressLayer];
}
return _gradientLayer;
}
CAGradientLayer 主要是实现图层渐变的一个类,它的使用很简单。
设置要渐变的颜色
[gradientLayer2 setColors:[NSArray arrayWithObjects:(id)[UIColor colorFromHexString:@"#4888f2"].CGColor,(id)[UIColor colorFromHexString:@"#46ddef"].CGColor, nil]];
设置渐变的起点跟结束点
[gradientLayer1 setStartPoint:CGPointMake(0.5, 1)];
[gradientLayer1 setEndPoint:CGPointMake(0.5, 0)];
如果将渐变图层直接添加到animationView的layer上显示效果如下:
//将渐变图层添加到animationView的图层上
[self.animationView.layer addSublayer:self.gradientLayer];
此时还没有动效也没有达到截取成圆的效果
要按照自己制定好的路径截取成圆,想到了CAShapeLayer这个类,这个类图层创建没有规定的形状,而是要自己定义一个path 让它按照path画出想要的形状,这里就结合了UIBezierPath类的使用,制定好贝赛尔曲线路径,画出颜色渐变的圆。
由于设计师要求绘制不完整的圆,所以绘制中,圆的起点,跟结束点有一定的弧度偏差,具体弧度如下:
#define degreesToRadians(x) (180 * (x)/M_PI) //把角度转换成PI的方式。 比如:degreesToRadians(90 - gapDegree/2),所以x一定要加括号。
#define halfGapRadian degreesToRadians(43)
- (CAShapeLayer *)progressLayer {
if (!_progressLayer) {
CGFloat lineWidth = 13.0;
CGFloat radius = kWidth/2 - lineWidth/2;
//图层画圆的轨迹
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(kWidth/2, kWidth/2) radius:radius startAngle:-M_PI_2*3 + halfGapRadian endAngle:M_PI_2-halfGapRadian clockwise:YES];
_progressLayer = [CAShapeLayer layer];
_progressLayer.path = path.CGPath;
_progressLayer.lineWidth = lineWidth;
_progressLayer.lineCap = @"round";
_progressLayer.strokeColor = [UIColor whiteColor].CGColor;
//将路径填充颜色设置为透明
_progressLayer.fillColor = [UIColor clearColor].CGColor;
}
return _progressLayer;
}
在gradientLayer的懒加载中加上如下一句代码:
[_gradientLayer setMask:self.progressLayer];
用progressLayer来截取渐变层,实现了颜色渐变圆的效果
现在已经是能够画出颜色渐变的圆了,但是没有加载过程的动画
想要让颜色渐变的圆 按照进度 在规定的时间画成圆,我想到的是利用CABasicAnimation类,来实现基本动画,实现代码如下:
//将渐变图层添加到animationView的图层上
[self.animationView.layer addSublayer:self.gradientLayer];
//动画时间
CGFloat duration = 1.0;
//进度程度
CGFloat progress = 1.0;
//strokeEnd 动画到某个点结束
CABasicAnimation *anim1 = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
anim1.removedOnCompletion = NO;
anim1.fillMode = kCAFillModeBoth;
anim1.duration = duration;
anim1.fromValue = @0.0;
anim1.toValue = @(progress);
//为图层添加动画
[self.progressLayer addAnimation:anim1 forKey:@"anim1"];
通过CABasicAnimation基本动画,利用keyPath “strokeEnd”从起点0,在规定的1.0秒内画圆到指定的prrogress进度,实现了动画绘制颜色渐变圆。
CABasicAnimation的动画执行需要在贝塞尔轨迹绘制的图层上,也就是为progressLayer 添加动画。
[self.progressLayer addAnimation:anim1 forKey:@"anim1"];
以上便是项目中实现动画绘制颜色渐变的圆的过程。