iOS 简单下载动画

作者: 宫城_ | 来源:发表于2016-03-27 21:56 被阅读621次

    这个动画比较简单基础,首先我们来看一下这个动画模拟的动图


    下载动画

    动画一共有四个状态,开始下载下载结束下载成功下载失败

    为什么会分有下载结束这样的状态呢?因为考虑到实际场景,可能会有在加载过程中,用户返回上级界面,我们需要结束下载动画


    我们按状态来实现,首先先看开始加载

    CABasicAnimation *rotationZAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    rotationZAnimation.fromValue = @(0);
    rotationZAnimation.toValue = @(M_PI*2);
    rotationZAnimation.repeatDuration = HUGE_VAL;
    rotationZAnimation.duration = 1.0;
    rotationZAnimation.cumulative = YES;
    rotationZAnimation.beginTime = CACurrentMediaTime();
    [self.loadingLayer addAnimation:rotationZAnimation forKey:@"rotationZAnimation"];
            
    NSArray *values = [self valueArrayWithWidth:self.downloadingViewWidth];
    CAKeyframeAnimation *boundsAnimation = [self bounsAnimationWithValues:values];
    [self.loadingLayer addAnimation:boundsAnimation forKey:nil];
    

    这里分为两个动画,一个是旋转动画,一个是放大缩小的动画
    旋转动画,我们只有一个初始值和末值,所以我们只需要使用CABasicAnimation就可以了,不需要使用CAKeyframeAnimation,CAKeyframeAnimation是用来处理关键帧动画的,它的values属性用来存储关键帧的值,这就是我们用来做处理放大缩小动画,上面代码可以看到我将它抽成了一个方法来用,因为在下载成功和失败的时候,成功和失败也是有放大缩小的动画,这三个其实是一个动画

    - (NSArray *)valueArrayWithWidth:(CGFloat)width {
        return @[[NSValue valueWithCGRect:CGRectMake(0, 0, width * 0.7, width * 0.7)],
                 [NSValue valueWithCGRect:CGRectMake(0, 0, width, width)],
                 [NSValue valueWithCGRect:CGRectMake(0, 0, width * 0.9, width * 0.9)]];
    }
    
    - (CAKeyframeAnimation *)bounsAnimationWithValues:(NSArray *)values {
        CAKeyframeAnimation *boundsAnimation = [CAKeyframeAnimation animationWithKeyPath:@"bounds"];
        boundsAnimation.duration = 0.6;
        boundsAnimation.beginTime = CACurrentMediaTime();
        boundsAnimation.values = values;
        boundsAnimation.keyTimes = @[@(0),@(0.3),@(0.6)];
        boundsAnimation.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
                                            [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut],
                                            [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
        boundsAnimation.removedOnCompletion = NO;
        boundsAnimation.fillMode = kCAFillModeForwards;
        return boundsAnimation;
    }
    

    我们统一设置动画的values值,这里传入的width值是下载的背景大小,因为下载圆圈有个放大的过程,所以我们需要圆圈的原始大小要比背景的大小小,所以我默认设置圆圈的大小是背景大小的0.9倍,所以动画的效果是圆圈从背景大小的0.7倍->背景大小->背景大小的0.9倍(圆圈的原始大小)
    在设置这个动画的时候,因为动画的值不止是初始值和末值,还是中间值,所以我使用CAKeyframeAnimation来做,每个关键帧之间的动画时间设置为0.3秒,这是最适合的动画时间,当然这是时间还是由自己反复调试动画决定的


    下载结束我们只要将转圈的动画移除掉即可,这样转圈就恢复到原来的状态了

    [self.loadingLayer removeAllAnimations];
    

    下载成功我们也需要将转圈动画移除,然后出现成功的动画,并且将成功图层的透明度从0变到1

    [self.loadingLayer removeAllAnimations];
    self.failLayer.opacity = 0.0;
    NSArray *values = [self valueArrayWithWidth:self.downloadingViewWidth * 0.5];
    CAKeyframeAnimation *boundsAnimation = [self bounsAnimationWithValues:values];
    [self.doneLayer addAnimation:boundsAnimation forKey:nil];
            
    [UIView animateWithDuration:1.0 animations:^{
        self.doneLayer.opacity = 1.0;
    }];
    

    下载失败也是同理

    [self.loadingLayer removeAllAnimations];
    self.doneLayer.opacity = 0.0;
    NSArray *values = [self valueArrayWithWidth:self.downloadingViewWidth * 0.5];
    CAKeyframeAnimation *boundsAnimation = [self bounsAnimationWithValues:values];
    [self.failLayer addAnimation:boundsAnimation forKey:nil];
            
    [UIView animateWithDuration:1.0 animations:^{
         self.failLayer.opacity = 1.0;
    }];
    

    好了,动画主要的原理就是这样,具体的代码实现可以看这里:https://github.com/Yuzeyang/DownloadingAnimation


    如果有什么意见或者建议,欢迎大家留言,知识是需要交流的,我相信会有更好更简洁的方法来处理

    这个是我的个人微信公众号,会不定期发表一些iOS开发文章以及疑难问题和我在阅读技术和非技术书籍的一些感悟,欢迎大家订阅!

    宫城Dev

    相关文章

      网友评论

      • mark666:有没有底层动画的博客,学习地址什么?
        宫城_:@mark666 关注
        宫城_:你可以专注一下叶孤城和kittenyang的博客

      本文标题:iOS 简单下载动画

      本文链接:https://www.haomeiwen.com/subject/lzhjlttx.html