利用CAGradientLayer绘制颜色渐变动画

来源:互联网 发布:心知天气 js调用示例 编辑:程序博客网 时间:2024/05/20 11:26

之前项目中,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"];

以上便是项目中实现动画绘制颜色渐变的圆的过程。

1 0