zoukankan      html  css  js  c++  java
  • 利用CALayer动画实现渐变进度条

    今天是第一次写博客,希望在今后的日子里大家可以共同进步提高。闲话不多说了,首先看一下效果图。

      其实这个空间是比较简单的调用CALayer动画的空间,首先我们做一下简单的分析。这个动画的组成分为两部分,第一部分为填充部分,即“strokeEnd”,另一部分则是填充颜色,即“stroke color”。有这两个动画组成了一个CALayer的组动画。

      实现原理大致明确我们来用代码实现一下,我们先修改一下它的初始化方法:

    -(instancetype)initWithFrameAndProsse:(CGRect)frame prosseInfo:(ProssenInfo)prosseInfo

    {

        self = [super initWithFrame:frame];

        if(self)

        {

            _prossenInfo             = prosseInfo;

           

            [self setCAShapeLayer];

        }

        return self;

    }

      这里面我将所需的一部分关于CAShapeLayer的参数写成了一个结构体,方便使用和查找,接下来我们初始化一下CAShapeLayer这个属性:

    -(void)setCAShapeLayer

    {

        _prosseShape                 = [CAShapeLayer layer];

        _prosseShape.strokeColor     = _prossenInfo.lineColor;

        _prosseShape.lineWidth       = _prossenInfo.width;

        _prosseShape.strokeStart     = 0;

        _prosseShape.strokeEnd       = 0;

        _prosseShape.path            = [self prossePath];

        _prosseShape.lineJoin        = kCALineJoinRound;

        _prosseShape.lineCap         = kCALineCapRound;

        _prosseShape.beginTime       =0.1f;

        

        [self.layer addSublayer:_prosseShape];

    }这里我们需要注意

       _prosseShape.lineJoin        = kCALineJoinRound;

        _prosseShape.lineCap         = kCALineCapRound;这两句话,如果不加上的话实现出来的进度条就不是圆角的。

    我们改如何给路径呢?

    -(AnimationPoint)animationPoint

    {

       

        CGFloat startPoint_x    = self.frame.size.width*(_prossenInfo.minLength<_prossenInfo.maxLength?_prossenInfo.minLength:_prossenInfo.maxLength);

        CGFloat endPoint_x      = self.frame.size.width*(_prossenInfo.minLength>_prossenInfo.maxLength?_prossenInfo.minLength:_prossenInfo.maxLength);

        

        AnimationPoint point    = AnimationPointMake\

                                  (CGPointMake(startPoint_x, self.frame.size.height/2.f-_prossenInfo.width/2.f), \

                                   CGPointMake(endPoint_x, self.frame.size.height/2.f-_prossenInfo.width/2.f));

        

        return point;

    }

    -(CGMutablePathRef)prossePath

    {

        AnimationPoint point    = [self animationPoint];

        CGMutablePathRef pathRef=CGPathCreateMutable();

        

        CGPathMoveToPoint(pathRef, NULL,point.startPoint.x, point.startPoint.y);

        

        CGPathAddLineToPoint(pathRef, NULL, point.endPoint.x,point.endPoint.y);

       

        CGPathCloseSubpath(pathRef);

       

        return pathRef;

    }

    我们给定了这个Layer的起始填充部分,颜色,宽度以及路径,接下来我们开始着手关于它的动画。

    -(void)starAnimation:(NSArray *)colorArray time:(NSTimeInterval)time

    {

       __block BOOL colors = NO;

        __weak CAShapeLayer *shape = _prosseShape;

        __block NSMutableArray *animationArray = [NSMutableArray array];

        _aniTime = time;

        

        [shape animateKey:@"strokeEnd"

                       fromValue:[NSNumber numberWithFloat:0.f]

                         toValue:[NSNumber numberWithFloat:0.5f]

                       customize:^BOOL(CABasicAnimation *animation) {

                           animation.duration = time;

                           if (colorArray != nil) {

                               colors  = YES;

                               [animationArray addObject:animation];

                               [shape keyAnimation:@"strokeColor"

                                                keyValues:colorArray

                                                customize:^BOOL(CAKeyframeAnimation *animation) {

                                                    animation.duration = time;

                                                     animation.calculationMode = kCAAnimationPaced;

                                                    [animationArray addObject:animation];

                                                    return colors;

                                                }];

                               [shape animationGroupWithDuration:time

                                                             animations:animationArray

                                                              customize:^(CAAnimationGroup *animation) {

                                                                 

                                                              }];

                           }

                           else

                           {

                               colors  = NO;

                               animation.delegate = self;

                           }

                           

                           return colors;

                       }];

    }

      因为我们要实现的事渐变颜色的动画效果,所以我们需要给定两个参数,一个是颜色数组,一个是进度时间。(当然在实际的下载过程中我们是不知道进度时间的,所以这里本人封装的控件还不具备很好的完整性,但是我们可以通过修改 toValue:[NSNumber numberWithFloat:0.5f]这个函数参数来实现下载进度,本人会在下篇博客之前修改完毕)。接下来我们实现一下关于动画时间的计算,因为CALayer动画本来是不支持动画时间监听的,所以这里面我用了一个定时器。

    -(void)animationDidStart:(CAAnimation *)anim

    {

        _animationTimer  = [NSTimer scheduledTimerWithTimeInterval:AnimationTimer target:self selector:@selector(progressDidStart:) userInfo:nil repeats:YES];

        

    }

    -(void)progressDidStart:(NSTimer *)timer

    {

        if (_delegate &&[_delegate respondsToSelector:@selector(prosseToPoint:withDot:)]) {

            animationProgress += 1/(_aniTime/AnimationTimer);

            if (animationProgress >= 1.0) {

                animationProgress = 1.0;

            }

            [_delegate prosseToPoint:CGPointZero withDot:animationProgress];

            

        }

    }

    -(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag

    {

        if (_delegate &&[_delegate respondsToSelector:@selector(prosseToPoint:withDot:)]) {

            animationProgress += 1/(_aniTime/AnimationTimer);

            if (animationProgress >= 1.0) {

                animationProgress = 1.0;

            }

            [_delegate prosseToPoint:CGPointZero withDot:animationProgress];

            

        }

        animationProgress = 0;

        [_animationTimer invalidate];

        _animationTimer = nil;

    }

      这样我们一个简单的进度条控件就写好了,下面我们来调用一下:

        _proView = [[XDProsseView alloc]initWithFrameAndProsse:CGRectMake(10, 320, self.view.bounds.size.width-20, 50) prosseInfo:ProssenInfoMake(5,1.f , 0.0, [UIColor blueColor].CGColor)];

        _proView.delegate = self;

        [self.view addSubview:_proView];

    初始化这个进度条,

       [_proView starAnimation:[NSArray arrayWithObjects:(id)[UIColor greenColor].CGColor,(id)[UIColor redColor].CGColor,(id)[UIColor blackColor].CGColor, nil] time:10.234f];

    设置开始,时间,颜色等。

    -(void)prosseToPoint:(CGPoint)point withDot:(double)dot

    {

    NSLog(@"监听进度条进度%@ %ld",NSStringFromCGPoint(point),dot);

    }

    第一次写博客,如果有什么不妥的地方,希望大家及时提出来,我一定会积极改正,谢谢!

  • 相关阅读:
    网络学习笔记
    zabbix4.2学习笔记系列
    ansible2.7学习笔记系列
    记一次磁盘UUID不能识别故障处理
    白话ansible-runner--1.环境搭建
    kubernetes的思考
    计算机网络原理精讲第六章--应用层
    计算机网络原理精讲第五章--传输层
    centos7下LVM挂载和扩容
    多线程下载命令--axel
  • 原文地址:https://www.cnblogs.com/xuruofan/p/4167505.html
Copyright © 2011-2022 走看看