美文网首页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地址

相关文章

  • 动画的分类和实现

    一、Transform动画 1.利用Transform的CGAffineTransformTranslate,可实...

  • 自定义动画

    动画分类: view动画(平移,旋转,缩放,透明度):xml和代码均可实现,建议用xml,因为xml 可读性高点 ...

  • 【Android 动画】帧动画、补间动画、属性动画

    分类 Android 官方提供了两种动画: 属性动画(Property Animation)通过改变对象的属性实现...

  • Android 动画机制

    一、Android的动画的分类:(实现方式有:xml资源文件方式,代码方式) 逐帧动画(Drawable An...

  • Android动画之视图动画

    分类 Android动画主要包括视图动画和属性动画。视图动画包括Tween动画和Frame动画。Tween动画又包...

  • Android 动画

    Android 动画分类: 传统动画 帧间动画 补间动画 属性动画ObjectAnimator 和 ValueAn...

  • 记:动画小总结

    总的来说,动画就是以上三个分类,下面详细解释各个分类及使用方法 一.View动画 View动画指定开始和结束的动画...

  • Android动画详解

    Android动画分类 Android动画分为传统动画和属性动画(Android3.0之后引入) 传统动画 帧动画...

  • android动画

    动画: 分类:分为视图动画和属性动画,其中视图动画又分为补间动画和逐帧动画。补间动画又分为平移动画、缩放动画、旋转...

  • 属性动画源码

    实现方法:利用属性动画,scaleX和scaleY,alpha,INTERPOLATOR来实现的动画效果。补间动画...

网友评论

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

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