美文网首页iOS_开发实战
动画的分类和实现

动画的分类和实现

作者: Andy_Livings | 来源:发表于2019-10-22 19:30 被阅读0次

    一、Transform动画

    1.利用Transform的CGAffineTransformTranslate,可实现上下左右的移动动画;

    首先定义一个用于显示动画的transformImageView,如下:

    @property(nonatomic,strong)UIImageView* transformImageView;
    

    (1)实现向上的动画,每次向上移动50个像素点:

        [UIView animateWithDuration:1.0 animations:^{
                self.transformImageView.transform = CGAffineTransformTranslate(self.transformImageView.transform, 0, -50);
            }];
    

    (2)实现向下的动画,每次向下移动50个像素点:

        [UIView animateWithDuration:1.0 animations:^{
         self.transformImageView.transform = CGAffineTransformTranslate(self.transformImageView.transform, 0, 50);
            }];
    

    (3)实现向左的动画,每次向左移动50个像素点:

        [UIView animateWithDuration:1.0 animations:^{
         self.transformImageView.transform = CGAffineTransformTranslate(self.transformImageView.transform, -50, 0);
            }];
    

    (4)实现向右的动画,每次向右移动50个像素点:

        [UIView animateWithDuration:1.0 animations:^{
        self.transformImageView.transform = CGAffineTransformTranslate(self.transformImageView.transform, 50, 0);
            }];
    

    2.利用Transform的CGAffineTransformScale,可以实现放大和缩小的动画;

    (1)实现放大的动画,每次放大的倍数为1.5:

        [UIView animateWithDuration:1.0 animations:^{
        self.transformImageView.transform = CGAffineTransformScale(self.transformImageView.transform, 1.5, 1.5);
            }];
    

    (2)实现缩小的动画,每次缩小的倍数为0.5:

        [UIView animateWithDuration:1.0 animations:^{
        self.transformImageView.transform = CGAffineTransformScale(self.transformImageView.transform, 0.5, 0.5);
            }];
    

    3.利用Transform的CGAffineTransformRotate,可以实现左右旋转动画。

    (1)实现向左旋转M_PI_4的动画:

        [UIView animateWithDuration:1.0 animations:^{
                self.transformImageView.transform = CGAffineTransformRotate(self.transformImageView.transform, -M_PI_4);
            }];
    

    (2)实现向右旋转M_PI_4的动画:

        [UIView animateWithDuration:1.0 animations:^{
         self.transformImageView.transform = CGAffineTransformRotate(self.transformImageView.transform, M_PI_4);
            }];
    

    二、序列帧动画

    一般项目中常见的动画有序列帧动画,比如著名的汤姆猫使用的就是这种类型的动画,下面介绍的是序列帧动画在项目中使用的场景。
    它是主要通过使用UIImageView的animationImages,animationRepeatCount,animationDuration等属性来实现的:
    首先定义一个用于显示汤姆猫的tomImageView,如下:

        @property (weak, nonatomic) IBOutlet UIImageView *tomImageView;
    
        /**
         序列帧动画实现
         @paramcount 总的图片张数
         @paramname 图片名称
         */
        - (void)runAnimationWithCount:(NSInteger)count name:(NSString*)name {
            if (self.tomImageView.isAnimating) return;
            NSMutableArray *imageArray = [NSMutableArray array];
            for(NSIntegeri =0; i < count; i++) {
                NSString*fileName = [NSStringstringWithFormat:@"%@_%02ld.jpg",name, i];
                NSString*filePath = [[NSBundlemainBundle]pathForResource:fileNameofType:nil];
                UIImage*image = [UIImageimageWithContentsOfFile:filePath];
        //        UIImage *image = [UIImage imageNamed:fileName];
                [imageArrayaddObject:image];
            }
            self.tomImageView.animationImages= imageArray;
            self.tomImageView.animationRepeatCount = 1;
            self.tomImageView.animationDuration= imageArray.count*0.15;
            [self.tomImageView startAnimating];
            CGFloat delay = self.tomImageView.animationDuration + 1.5; 
            [self.tomImageViewperformSelector:@selector(setAnimationImages:)withObject:nilafterDelay:delay];
        }
    

    三、Lottie动画

    可以使用Lottie这个第三方库实现动画。

    (1)首先通过cocopoads导入这个类库,如下:

            project ‘Animation.xcodeproj'
            platform :ios, '9.0'
            target ‘Animation’ do
               pod 'lottie-ios'
            end
    

    (2)导入头文件,如下:

            #import <Lottie/Lottie.h>
    

    (3) LOTAnimationView的动画实现:

        /**
         LotAnimation的动画实现
         @paramanimationName 动画名称
         */
        - (void)runLotAnimationViewWithAnimationName:(NSString*)animationName {
            if (self.isAnimating) return;
            LOTAnimationView*animationView = [LOTAnimationViewanimationNamed:animationName];
            animationView.contentMode = UIViewContentModeScaleAspectFill;
         animationView.frame=CGRectMake(self.view.frame.size.width/2-150,100,300,200);
            animationView.animationProgress=0;
            [animationViewplay];
            [self.viewaddSubview:animationView];
            self.isAnimating = YES;
            // 实现动画音效
            [MusicPlayerHelper playAudioWithAudioName:@"like_normal_audio"];
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [animationViewremoveFromSuperview];
                self.isAnimating=NO;
            });
        }
    

    四、核心动画

    核心动画常见的主要有CABasicAnimation、CAKeyframeAnimation、CATransition等。下面分别对它们进行介绍。

    (1)CABasicAnimation

    @property (nonatomic, strong) CALayer * layer;
    

    在viewDidLoad中实现如下方法

    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        
        CALayer *layer = [CALayer layer];
        layer.position = CGPointMake(100, 100);
        layer.bounds = CGRectMake(0, 0, 100, 100);
        layer.backgroundColor = [UIColor redColor].CGColor;
        [self.view.layer addSublayer:layer];
        self.layer = layer;
    }
    

    (a)CABasicAnimation的平移动画

    /// 平移
    - (void)animationWithTranslate {
        
        // 1.创建动画对象
        CABasicAnimation *anima = [CABasicAnimation animation];
        
        // 2.设置动画对象
        // keyPath决定了执行怎样的动画,调整哪个属性来执行动画
        anima.keyPath = @"position";
    //    anima.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
        // toValue : 最终变成什么值
        // byValue : 增加多少值
        anima.byValue = [NSValue valueWithCGPoint:CGPointMake(200, 300)];
        anima.duration = 2.0;
        
        /**让图层保持动画执行完毕后的状态**/
        // 动画执行完毕后不要删除动画
        anima.removedOnCompletion = NO;
        // 保持最新的状态
        anima.fillMode = kCAFillModeForwards;
        
        // 3.添加动画
        [self.layer addAnimation:anima forKey:nil];
    }
    

    (b)CABasicAnimation的缩放动画

    /// 缩放
    - (void)animationWithScale {
        
        // 1.创建动画对象
        CABasicAnimation *anima = [CABasicAnimation animation];
        
        // 2.设置动画对象
        // keyPath决定了执行怎样的动画,调整哪个属性来执行动画
        anima.keyPath = @"bounds";
    //    anima.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
        anima.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 200, 200)];
        anima.duration = 2.0;
        
        /**让图层保持动画执行完毕后的状态**/
        // 动画执行完毕后不要删除动画
        anima.removedOnCompletion = NO;
        // 保持最新的状态
        anima.fillMode = kCAFillModeForwards;
        
        // 3.添加动画
        [self.layer addAnimation:anima forKey:nil];
    }
    

    (c)CABasicAnimation的旋转动画

    /// 旋转
    - (void)animationWithRotate {
        
        // 1.创建动画对象
        CABasicAnimation *anima = [CABasicAnimation animation];
        
        // 2.设置动画对象
        // keyPath决定了执行怎样的动画,调整哪个属性来执行动画
        anima.keyPath = @"transform";
    //    anima.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
        anima.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI, 1, -1, 0)];
        anima.duration = 2.0;
        
        anima.removedOnCompletion = NO;
        anima.fillMode = kCAFillModeForwards;
        
        // 3.添加动画
        [self.layer addAnimation:anima forKey:nil];
    }
    

    (d)CABasicAnimation的变换动画

    /// 变换
    - (void)animationWithTransform {
        
        // 1.创建动画对象
        CABasicAnimation *anima = [CABasicAnimation animation];
        
        // 2.设置动画对象
        // keyPath决定了执行怎样的动画,调整哪个属性来执行动画
    //     anima.keyPath = @"transform.rotation";
    //     anima.keyPath = @"transform.scale.x";
        anima.keyPath = @"transform.translation.x";
        anima.toValue = @(100);
    //    anima.toValue = [NSValue valueWithCGPoint:CGPointMake(100, 100)];
        anima.duration = 2.0;
        
        anima.removedOnCompletion = NO;
        anima.fillMode = kCAFillModeForwards;
        
        // 3.添加动画
        [self.layer addAnimation:anima forKey:nil];
    }
    

    (2)CAKeyframeAnimation

    @property (weak, nonatomic) IBOutlet UIView *redView;
    

    (a)CAKeyframeAnimation 的位置变换

    - (void)animationWithMove {
        
        // CABasicAnimation fromValue --> toValue
        
        CAKeyframeAnimation *anima = [CAKeyframeAnimation animation];
        
        anima.keyPath = @"position";
        
        NSValue *v1 = [NSValue valueWithCGPoint:CGPointZero];
        NSValue *v2 = [NSValue valueWithCGPoint:CGPointMake(100, 0)];
        NSValue *v3 = [NSValue valueWithCGPoint:CGPointMake(100, 200)];
        NSValue *v4 = [NSValue valueWithCGPoint:CGPointMake(0, 200)];
        anima.values = @[v1, v2, v3, v4];
        
    //    anima.keyTimes = @[@(0.5), @(0.25), @(0.25)];
        
        anima.duration = 2.0;
        
        anima.removedOnCompletion = NO;
        anima.fillMode = kCAFillModeForwards;
        
        [self.redView.layer addAnimation:anima forKey:nil];
    }
    

    (b)CAKeyframeAnimation 的动画执行节奏变换

    - (void)animationWithPosition {
        
        CAKeyframeAnimation *anima = [CAKeyframeAnimation animation];
        
        anima.keyPath = @"position";
        anima.removedOnCompletion = NO;
        anima.fillMode = kCAFillModeForwards;
        anima.duration = 2.0;
        
        CGMutablePathRef path = CGPathCreateMutable();
        CGPathAddEllipseInRect(path, NULL, CGRectMake(100, 100, 200, 200));
        anima.path = path;
        CGPathRelease(path);
        
        // 设置动画的执行节奏
        // kCAMediaTimingFunctionEaseInEaseOut : 一开始比较慢, 中间会加速,  临近结束的时候, 会变慢
        anima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        anima.delegate = self;
        
        [self.redView.layer addAnimation:anima forKey:nil];
    }
    
    #pragma mark - 动画的代理方法
    
    #pragma mark 动画开始的时候调用
    - (void)animationDidStart:(CAAnimation *)anim {
        
        NSLog(@"animationDidStart");
    }
    
    - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
        
        NSLog(@"animationDidStop");
    }
    

    (c)CAKeyframeAnimation 的抖动效果

    首先定义宏如下:
    #define Angle2Radian(angle) ((angle) / 180.0 * M_PI)
    
    @property (weak, nonatomic) IBOutlet UIImageView *iconView;
    

    主要代码如下:

    - (IBAction)start {
        
        CAKeyframeAnimation *anima = [CAKeyframeAnimation animation];
        anima.keyPath = @"transform.rotation";
        
        anima.values = @[@(Angle2Radian(-5)), @(Angle2Radian(5)), @(Angle2Radian(-5))];
        anima.duration = 0.25;
        // 动画的重复执行次数
        anima.repeatCount = MAXFLOAT;
        
        // 保持动画执行完毕后的状态
        anima.removedOnCompletion = NO;
        anima.fillMode = kCAFillModeForwards;
        
        [self.iconView.layer addAnimation:anima forKey:@"shake"];
    }
    
    - (IBAction)stop {
        
        [self.iconView.layer removeAnimationForKey:@"shake"];
    }
    

    (3) CATransition

    转场动画

    @property (weak, nonatomic) IBOutlet UIImageView *iconView;
    
    /// 当前图片的索引
    @property (nonatomic, assign) NSInteger currentIndex;
    

    主要代码示例如下:

    - (IBAction)pre {
        
        self.currentIndex--;
        if (self.currentIndex == -1) {
            self.currentIndex = 8;
        }
        
        NSString *fileName = [NSString stringWithFormat:@"%ld.jpg", self.currentIndex + 1];
        self.iconView.image = [UIImage imageNamed:fileName];
        
        CATransition *anima = [CATransition animation];
    //    anima.type = @"cube";
    //    anima.subtype = kCATransitionFromLeft;
        anima.type = @"pageUnCurl";
        anima.duration = 0.5;
        [self.view.layer addAnimation:anima forKey:nil];
        
    }
    
    - (IBAction)next {
        
        self.currentIndex++;
        if (self.currentIndex == 9) {
            self.currentIndex = 0;
        }
        
        NSString *fileName = [NSString stringWithFormat:@"%ld.jpg", self.currentIndex + 1];
        self.iconView.image = [UIImage imageNamed:fileName];
        
        // 转场动画
        CATransition *anima = [CATransition animation];
        anima.type = @"pageCurl";
    //    anima.subtype = kCATransitionFromRight;
        anima.duration = 0.5;
        
    //    anima.startProgress = 0.0;
    //    anima.endProgress = 0.5;
        
        [self.view.layer addAnimation:anima forKey:nil];
    }
    

    (4)CAAnimationGroup

    可以使用CAAnimationGroup组合多种动画,实现多种复杂的动画效果。

    @property (weak, nonatomic) IBOutlet UIView *myView;
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        
        // 1.创建旋转动画对象
        CABasicAnimation *rotate = [CABasicAnimation animation];
        rotate.keyPath = @"transform.rotation";
        rotate.toValue = @(M_PI);
        
        // 2.创建缩放动画对象
        CABasicAnimation *scale = [CABasicAnimation animation];
        scale.keyPath = @"transform.scale";
        scale.toValue = @(0.0);
        
        // 3.平移动画
        CABasicAnimation *move = [CABasicAnimation animation];
        move.keyPath = @"transform.translation";
        move.toValue = [NSValue valueWithCGPoint:CGPointMake(100, 100)];
        
        // 4.将所有的动画添加到动画组中
        CAAnimationGroup *group = [CAAnimationGroup animation];
        group.animations = @[rotate, scale, move];
        group.duration = 2.0;
        group.removedOnCompletion = NO;
        group.fillMode = kCAFillModeForwards;
        
        [self.myView.layer addAnimation:group forKey:nil];
    }
    

    今天的分享到这里就结束了,谢谢大家!

    Demo地址

    相关文章

      网友评论

        本文标题:动画的分类和实现

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