利用CAGradientLayer绘制颜色渐变动画

时间:2022-04-24 23:20:50

之前项目中,UI设计师要求金融理财模块做成如下效果图:
利用CAGradientLayer绘制颜色渐变动画
其中有涉及相应的动画 比如类似进度条图层颜色渐变动画,现将实现记录如下:

图层颜色渐变主要通过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];

利用CAGradientLayer绘制颜色渐变动画
此时还没有动效也没有达到截取成圆的效果
要按照自己制定好的路径截取成圆,想到了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来截取渐变层,实现了颜色渐变圆的效果
利用CAGradientLayer绘制颜色渐变动画
现在已经是能够画出颜色渐变的圆了,但是没有加载过程的动画
想要让颜色渐变的圆 按照进度 在规定的时间画成圆,我想到的是利用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"];

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