• 动画(Animation) 、 高级动画(Core Animation)


    1 演示UIImage制作的动画

    1.1 问题

    UIImage动画是IOS提供的最基本的动画,通常用于制作一些小型的动画,本案例使用UIImage制作一个小狗跑动的动画,如图-1所示:

    图-1

    1.2 方案

    首先在创建好的Xcode项目的Storyboard中拖放一个ImageView控件,并关联成TRViewController的属性imageView。

    然后在viewDidLoad方法中使用工厂方法animatedImageNamed:创建UIImage对象image。

    最后将imageView的image属性设置为刚才创建的image对象即可。

    1.3 步骤

    实现此案例需要按照如下步骤进行。

    步骤一:拖放ImageView控件

    首先在创建好的Xcode项目的Storyboard中拖放一个ImageView控件,并关联成TRViewController的属性imageView,代码如下所示:

    1. @interface TRViewController ()
    2. @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    3. @end

    步骤二:使用UIImage生成动画

    首先导入图片素材,图片的命名规则是按顺序命名,即每张图片的名称前半部分一样后半部分是序号,例如:0_0_run_00、0_0_run_01、0_0_run_02……

    然后在viewDidLoad方法中使用工厂方法animatedImageNamed:创建UIImage对象image,这里需要注意的是imageNamed参数,传入的是图片名称不带序号的部分。

    最后将imageView的image属性设置为刚才创建的image对象,代码如下所示:

     
    1. - (void)viewDidLoad
    2. {
    3. [super viewDidLoad];
    4. UIImage *image = [UIImage animatedImageNamed:@"0_0_run_" duration:2];
    5. self.imageView.image = image;
    6. }

    1.4 完整代码

    本案例中,TRViewController.m文件中的完整代码如下所示:

     
    1. #import "TRViewController.h"
    2. @interface TRViewController ()
    3. @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    4. @end
    5. @implementation TRViewController
    6. - (void)viewDidLoad
    7. {
    8. [super viewDidLoad];
    9. UIImage *image = [UIImage animatedImageNamed:@"0_0_run_" duration:2];
    10. self.imageView.image = image;
    11. }
    12. @end
     

    2 使用NSTimer做一个图片淡入的效果

    2.1 问题

    NSTimer是一个计时器类,用于定时向指定对象发送消息,本案例使用NSTimer制作一个图片淡入的效果,即每隔一定的时间改变图片的alpha值,如图-2所示:

    图-2

    2.2 方案

    首先在创建好的Xcode项目的Storyboard中拖放一个和屏幕一样大小的ImageView控件,并将ImageView设置为TRViewController的属性imageView。

    然后在viewDidLoad方法中创建一个计时器,每隔1/30秒重复调用方法changeAlpha:。

    最后实现方法changeAlpha:,每次调用都改变imageView的alpha值。

    2.3 步骤

    实现此案例需要按照如下步骤进行。

    步骤一:拖放ImageView控件

    首先在创建好的Xcode项目的Storyboard中拖放一个和屏幕一样大小的ImageView控件,在右边栏的检查器中给ImageView设置image,并将ImageView设置为TRViewController的属性imageView,代码如下所示:

     
    1. @interface TRViewController ()
    2. @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    3. @end

    步骤二:创建计时器

    在viewDidLoad方法中创建一个计时器,每隔1/30秒重复调用方法changeAlpha:,代码如下所示:

    1. - (void)viewDidLoad
    2. {
    3. [super viewDidLoad];
    4.     [NSTimer scheduledTimerWithTimeInterval:1/FPS target:self selector:@selector(changeAlpha:) userInfo:nil repeats:YES];
    5. }

    步骤三:实现changeAlpha:方法

    首先定义两个宏FPS用来表示帧率,DURATION用来表示动画时长,在changeAlpha:方法中根据FPS和DURATION计算imageView的alpha值,代码如下所示:

     
    1. #define FPS 30.0 //帧率
    2. #define DURATION 5.0 //动画时长
    3. //当前值=开始值+当前的帧数*(结束值-开始值)/(帧率*时长)
    4. - (void)changeAlpha:(NSTimer *)timer
    5. {
    6. static NSUInteger count = 0;
    7. count++;
    8. self.imageView.alpha = count * 1.0/(FPS * DURATION);
    9. if (count >= FPS * DURATION) {
    10. [timer invalidate];
    11. }
    12. }

    2.4 完整代码

    本案例中,TRViewController.m文件中的完整代码如下所示:

     
    1. #import "TRViewController.h"
    2. @interface TRViewController ()
    3. @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    4. @end
    5. @implementation TRViewController
    6. #define FPS 30.0 //帧率
    7. #define DURATION 5.0 //动画时长
    8. - (void)viewDidLoad
    9. {
    10. [super viewDidLoad];
    11.     [NSTimer scheduledTimerWithTimeInterval:1/FPS target:self selector:@selector(changeAlpha:) userInfo:nil repeats:YES];
    12. }
    13. //当前值=开始值+当前的帧数*(结束值-开始值)/(帧率*时长)
    14. - (void)changeAlpha:(NSTimer *)timer
    15. {
    16. static NSUInteger count = 0;
    17. count++;
    18. self.imageView.alpha = count * 1.0/(FPS * DURATION);
    19. if (count >= FPS * DURATION) {
    20. [timer invalidate];
    21. }
    22. }
    23. @end
     

    3 使用UIView制作动画

    3.1 问题

    UIView动画是UIKit提供专门制作动画的API,其本质是对CoreAnimation的封装,使用UIView可以轻松方便的实现动画,不需要经过任何计算,本案例使用UIView制作一个飞机移动的动画,如图-3所示:

    图-3

    3.2 方案

    首先在创建好的Xcode项目的Storyboard中拖放一个ImageView控件和一个Label控件,在右边栏的检查器中分别设置ImageView和Label的显示图片和文字,ImageView显示飞机图片,Label显示文字“Welcome To iGame“,并将ImageView和Label关联成TRViewController的属性aircraft和welcomeLabel。

    然后在Storyboard中拖放一个Button对象,设置标题为Start,并关联成TRViewController的方法start:。

    最后在viewDidLoad方法中使用UIView的动画方法实现aircraft和welcomeLabel的入场动画,并在方法start:中使用UIView的动画方法实现飞机的飞行动画。

    3.3 步骤

    实现此案例需要按照如下步骤进行。

    步骤一:搭建界面

    首先在创建好的Xcode项目的Storyboard中拖放一个ImageView控件和一个Label控件,在右边栏的检查器中分别设置ImageView和Label的显示图片和文字,ImageView显示飞机图片,Label显示文字“Welcome To iGame“。

    其次将ImageView和Label关联成TRViewController的属性aircraft和welcomeLabel,代码如下所示:

    1. @interface TRViewController ()
    2. @property (weak, nonatomic) IBOutlet UILabel *welcomeLabel;
    3. @property (weak, nonatomic) IBOutlet UIImageView *aircraft;
    4. @end

    然后在Storyboard中拖放一个Button对象,设置标题为Start,并关联成TRViewController的方法start:。

    最后Storyboard中完成的界面如图-4所示:

    图-4

    步骤二:使用UIView实现动画

    首先在viewDidLoad方法中使用UIView的动画方法实现welcomeLabel的入场动画,welcomeLabel从屏幕的左方进入屏幕,使用UIView的动画方法animateWithDuration: delay: usingSpringWithDamping: initialSpringVelocity: options:增加弹簧效果,代码如下所示:

     
    1. - (void)viewDidAppear:(BOOL)animated
    2. {
    3. [super viewDidAppear:animated];
    4. //结束位置
    5.     CGRect endFrame = self.welcomeLabel.frame;
    6. //开始位置
    7. CGRect startFrame = endFrame;
    8. startFrame.origin.x = - startFrame.size.width;
    9. //welcome的入场动画
    10. self.welcomeLabel.frame = startFrame;
    11. self.welcomeLabel.alpha = 0.1;
    12. [UIView animateWithDuration:5.0 delay:0.3 usingSpringWithDamping:0.1 initialSpringVelocity:5 options:UIViewAnimationOptionCurveEaseInOut animations:^{
    13. self.welcomeLabel.frame = endFrame;
    14. self.welcomeLabel.alpha = 1.0;
    15. } completion:^(BOOL finished) {
    16. NSLog(@"动画结束");
    17. }];
    18. }

    然后实现飞机的入场动画,飞机从屏幕的下方飞入屏幕,代码如下所示:

     
    1. - (void)viewDidAppear:(BOOL)animated
    2. {
    3. [super viewDidAppear:animated];
    4. //结束位置
    5.     CGRect endFrame = self.welcomeLabel.frame;
    6. //开始位置
    7. CGRect startFrame = endFrame;
    8. startFrame.origin.x = - startFrame.size.width;
    9. //welcome的入场动画
    10. self.welcomeLabel.frame = startFrame;
    11. self.welcomeLabel.alpha = 0.1;
    12. [UIView animateWithDuration:5.0 delay:0.3 usingSpringWithDamping:0.1 initialSpringVelocity:5 options:UIViewAnimationOptionCurveEaseInOut animations:^{
    13. self.welcomeLabel.frame = endFrame;
    14. self.welcomeLabel.alpha = 1.0;
    15. } completion:^(BOOL finished) {
    16. NSLog(@"动画结束");
    17. }];
    18. //飞机的入场动画
    19. endFrame = self.aircraft.frame;
    20. startFrame = endFrame;
    21. startFrame.origin.y = self.view.bounds.size.height;
    22. self.aircraft.frame = startFrame;
    23. [UIView animateWithDuration:2.0 animations:^{
    24. self.aircraft.frame = endFrame;
    25. }];
    26. }

    最后实现方法start:完成飞机的飞行动画,飞机从屏幕下方飞到屏幕上方,并且在动画结束之后反复在屏幕中飞行,代码如下所示:

     
    1. - (IBAction)start:(UIButton *)sender
    2. {
    3. CGPoint point = self.aircraft.center;
    4. point.y = 80;
    5. [UIView animateWithDuration:3.0 delay:1.0 options:UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionRepeat|UIViewAnimationOptionAutoreverse animations:^{
    6. self.aircraft.center = point;
    7. } completion:^(BOOL finished) {
    8. NSLog(@"动画结束");
    9. }];
    10. }

    3.4 完整代码

    本案例中,TRViewController.m文件中的完整代码如下所示:

     
    1. #import "TRViewController.h"
    2. @interface TRViewController ()
    3. @property (weak, nonatomic) IBOutlet UILabel *welcomeLabel;
    4. @property (weak, nonatomic) IBOutlet UIImageView *aircraft;
    5. @end
    6. @implementation TRViewController
    7. - (void)viewDidAppear:(BOOL)animated
    8. {
    9. [super viewDidAppear:animated];
    10. //结束位置
    11.     CGRect endFrame = self.welcomeLabel.frame;
    12. //开始位置
    13. CGRect startFrame = endFrame;
    14. startFrame.origin.x = - startFrame.size.width;
    15. //welcome的入场动画
    16. self.welcomeLabel.frame = startFrame;
    17. self.welcomeLabel.alpha = 0.1;
    18. [UIView animateWithDuration:5.0 delay:0.3 usingSpringWithDamping:0.1 initialSpringVelocity:5 options:UIViewAnimationOptionCurveEaseInOut animations:^{
    19. self.welcomeLabel.frame = endFrame;
    20. self.welcomeLabel.alpha = 1.0;
    21. } completion:^(BOOL finished) {
    22. NSLog(@"动画结束");
    23. }];
    24. //飞机的入场动画
    25. endFrame = self.aircraft.frame;
    26. startFrame = endFrame;
    27. startFrame.origin.y = self.view.bounds.size.height;
    28. self.aircraft.frame = startFrame;
    29. [UIView animateWithDuration:2.0 animations:^{
    30. self.aircraft.frame = endFrame;
    31. }];
    32. }
    33. - (IBAction)start:(UIButton *)sender
    34. {
    35. CGPoint point = self.aircraft.center;
    36. point.y = 80;
    37. [UIView animateWithDuration:3.0 delay:1.0 options:UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionRepeat|UIViewAnimationOptionAutoreverse animations:^{
    38. self.aircraft.center = point;
    39. } completion:^(BOOL finished) {
    40. NSLog(@"动画结束");
    41. }];
    42. }
    43. @end
     

    4 CALayer的简单应用

    4.1 问题

    任何UIView及子类对象都有一个属性叫layer,此属性就是UIView的CoreAnimation层,类型是CALayer,本案例演示CALayer如何使用,如图-5所示:

    图-5

    4.2 方案

    首先在创建好的Xcode项目的Storyboard中拖放一个ImageView控件,在右边栏的检查器中设置ImageView的显示图片,并将ImageView和Label关联成TRViewController的属性imageView。

    然后在viewDidLoad方法中设置self.view的layer的背景颜色和圆角。再设置imageView的layer属性,将layer设置完圆角之后要将遮罩打开。

    最后在viewDidLoad方法中分别给self.view.layer添加一个无图片的子层和有图片的子层。

    4.3 步骤

    实现此案例需要按照如下步骤进行。

    步骤一:搭建Storyboard界面

    首先在创建好的Xcode项目的Storyboard中拖放一个ImageView控件,在右边栏的检查器中设置ImageView的显示图片,并将ImageView和Label关联成TRViewController的属性imageView,代码如下所示:

    1. @interface TRViewController ()
    2. @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    3. @end

    步骤二:设置layer属性

    首先在viewDidLoad方法中设置self.view的layer的背景颜色和圆角,代码如下所示:

    1. - (void)viewDidLoad
    2. {
    3. [super viewDidLoad];
    4. //设置view的layer
    5.     CALayer *layer = self.view.layer;
    6. layer.backgroundColor = [[UIColor orangeColor] CGColor];
    7. layer.cornerRadius = 30.0;
    8. }

    运行程序发现背景变成圆角的,如图-6所示:

    图-6

    其次再设置imageView的layer属性,将layer设置完圆角之后要将遮罩打开,代码如下所示:

     
    1. - (void)viewDidLoad
    2. {
    3. [super viewDidLoad];
    4. //设置view的layer
    5.     CALayer *layer = self.view.layer;
    6. layer.backgroundColor = [[UIColor orangeColor] CGColor];
    7. layer.cornerRadius = 30.0;
    8. //将imageView设置成圆角
    9. self.imageView.layer.cornerRadius = 10.0;
    10. //打开遮罩,否则无效
    11. self.imageView.layer.masksToBounds =YES;
    12. }

    然后在viewDidLoad方法中给self.view.layer添加一个无图片的子层,代码如下所示:

     
    1. - (void)viewDidLoad
    2. {
    3. [super viewDidLoad];
    4. //设置view的layer
    5.     CALayer *layer = self.view.layer;
    6. layer.backgroundColor = [[UIColor orangeColor] CGColor];
    7. layer.cornerRadius = 30.0;
    8. //将imageView设置成圆角
    9. self.imageView.layer.cornerRadius = 10.0;
    10. //打开遮罩,否则无效
    11. self.imageView.layer.masksToBounds =YES;
    12. //加子层
    13. CALayer *subLayer = [CALayer layer];
    14. subLayer.backgroundColor = [UIColor purpleColor].CGColor;
    15. subLayer.frame = CGRectMake(30, 200, 100, 120);
    16. //设置阴影
    17. subLayer.shadowColor = [UIColor greenColor].CGColor;
    18. subLayer.shadowOffset = CGSizeMake(2, 2);
    19. subLayer.shadowRadius = 5.0;
    20. subLayer.shadowOpacity = 0.8;
    21. //设置圆角
    22. subLayer.cornerRadius = 10.0;
    23. [layer addSublayer:subLayer];
    24. }

    最后在viewDidLoad方法中给self.view.layer添加一个有图片的子层,代码如下所示:

     
    1. - (void)viewDidLoad
    2. {
    3. [super viewDidLoad];
    4. //设置view的layer
    5.     CALayer *layer = self.view.layer;
    6. layer.backgroundColor = [[UIColor orangeColor] CGColor];
    7. layer.cornerRadius = 30.0;
    8. //将imageView设置成圆角
    9. self.imageView.layer.cornerRadius = 10.0;
    10. //打开遮罩,否则无效
    11. self.imageView.layer.masksToBounds =YES;
    12. //加子层
    13. CALayer *subLayer = [CALayer layer];
    14. subLayer.backgroundColor = [UIColor purpleColor].CGColor;
    15. subLayer.frame = CGRectMake(30, 200, 100, 120);
    16. subLayer.shadowColor = [UIColor greenColor].CGColor;
    17. subLayer.shadowOffset = CGSizeMake(2, 2);
    18. subLayer.shadowRadius = 5.0;
    19. subLayer.shadowOpacity = 0.8;
    20. subLayer.cornerRadius = 10.0;
    21. [layer addSublayer:subLayer];
    22. //加有内容的子层
    23. CALayer *imageLayer = [CALayer new];
    24. imageLayer.frame = CGRectMake(180, 300, 100, 120);
    25. //设置层的内容
    26. imageLayer.contents = (id)[UIImage imageNamed:@"d.jpg"].CGImage;
    27. imageLayer.cornerRadius = 10.0;
    28. imageLayer.masksToBounds = YES;
    29. [layer addSublayer:imageLayer];
    30. }

    4.4 完整代码

    本案例中,TRViewController.m文件中的完整代码如下所示:

     
    1. #import "TRViewController.h"
    2. @interface TRViewController ()
    3. @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    4. @end
    5. @implementation TRViewController
    6. - (void)viewDidLoad
    7. {
    8. [super viewDidLoad];
    9. //设置view的layer
    10.     CALayer *layer = self.view.layer;
    11. layer.backgroundColor = [[UIColor orangeColor] CGColor];
    12. layer.cornerRadius = 30.0;
    13. //将imageView设置成圆角
    14. self.imageView.layer.cornerRadius = 10.0;
    15. //打开遮罩,否则无效
    16. self.imageView.layer.masksToBounds =YES;
    17. //加子层
    18. CALayer *subLayer = [CALayer layer];
    19. subLayer.backgroundColor = [UIColor purpleColor].CGColor;
    20. subLayer.frame = CGRectMake(30, 200, 100, 120);
    21. subLayer.shadowColor = [UIColor greenColor].CGColor;
    22. subLayer.shadowOffset = CGSizeMake(2, 2);
    23. subLayer.shadowRadius = 5.0;
    24. subLayer.shadowOpacity = 0.8;
    25. subLayer.cornerRadius = 10.0;
    26. [layer addSublayer:subLayer];
    27. //加有内容的子层
    28. CALayer *imageLayer = [CALayer new];
    29. imageLayer.frame = CGRectMake(180, 300, 100, 120);
    30. imageLayer.contents = (id)[UIImage imageNamed:@"d.jpg"].CGImage;
    31. imageLayer.cornerRadius = 10.0;
    32. imageLayer.masksToBounds = YES;
    33. [layer addSublayer:imageLayer];
    34. }
    35. @end
     

    5 使用CoreAnimation制作动画

    5.1 问题

    CoreAnimation是一个图形渲染和动画的底层框架,能够提供更多更强大的图形渲染显示效果。本案例使用CoreAnimation的关键帧动画方法和基础动画方法制作动画,如图-7所示:

    图-7

    5.2 方案

    首先在创建好的Xcode项目的Storyboard中拖放一个ImageView控件和一个Button控件,在右边栏的检查器中设置ImageView和Button的属性,并将ImageView关联成TRAnimationViewController的属性imageView,将Button关联成TRAnimationViewController的方法start:。

    然后在viewDidLoad方法中设置imageView的layer属性,将imageView设置成圆角。

    最后实现start:方法,当点击按钮imageView开始执行动画。首先制定一个imageView的动画路径path,是一个UIBezierPath类型,然后分别创建关键帧动画、缩放动画以及透明度改变动画,最后将以上动画放进一个动画群组里面,即CAAnimationGroup类型的group,并将动画添加到imageView的layer中。

    5.3 步骤

    实现此案例需要按照如下步骤进行。

    步骤一:搭建Storyboard界面

    首先在创建好的Xcode项目的Storyboard中拖放一个ImageView控件和一个Button控件,在右边栏的检查器中设置ImageView和Button的属性,并将ImageView关联成TRAnimationViewController的属性imageView,将Button关联成TRAnimationViewController的方法start:,代码如下所示:

     
    1. @interface TRAnimationViewController ()
    2. @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    3. @end
    4. - (IBAction)start:(id)sender
    5. {
    6. }

    步骤二:实现imageView的移动动画

    首先在viewDidLoad方法中设置imageView的layer属性,将imageView设置成圆角,代码如下所示:

     
    1. - (void)viewDidLoad
    2. {
    3. [super viewDidLoad];
    4. //设置imageView的layer属性
    5.     self.imageView.layer.cornerRadius = 8.0;
    6. self.imageView.layer.masksToBounds = YES;
    7. }

    然后实现start:方法,当点击按钮imageView开始执行动画。首先制定一个imageView的动画路径path,是一个UIBezierPath类型,代码如下所示:

    1. - (IBAction)start:(id)sender
    2. {
    3. UIBezierPath *path = [UIBezierPath bezierPath];
    4. [self createCurve:path];
    5. }
    6. - (IBAction)start:(id)sender
    7. {
    8. UIBezierPath *path = [UIBezierPath bezierPath];
    9. [self createCurve:path];
    10. //创建关键帧
    11. CAKeyframeAnimation *moveAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    12. //设置相关属性
    13. moveAnimation.path = path.CGPath;
    14. moveAnimation.removedOnCompletion = YES;
    15. }

    然后创建关键帧动画,并设置相关属性,代码如下所示:

    1. - (IBAction)start:(id)sender
    2. {
    3. UIBezierPath *path = [UIBezierPath bezierPath];
    4. [self createCurve:path];
    5. //创建关键帧
    6. CAKeyframeAnimation *moveAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    7. //设置相关属性
    8. moveAnimation.path = path.CGPath;
    9. moveAnimation.removedOnCompletion = YES;
    10. }

    再创建缩放动画以及透明度改变动画,代码如下所示:

     
    1. - (IBAction)start:(id)sender
    2. {
    3. UIBezierPath *path = [UIBezierPath bezierPath];
    4. [self createCurve:path];
    5. //创建关键帧
    6. CAKeyframeAnimation *moveAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    7. //设置相关属性
    8. moveAnimation.path = path.CGPath;
    9. moveAnimation.removedOnCompletion = YES;
    10. //创建缩放动画
    11. CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
    12. scaleAnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
    13. scaleAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.1, 0.1, 1.0)];
    14. scaleAnimation.removedOnCompletion = YES;
    15. //创建透明度动画
    16. CABasicAnimation *alphaAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
    17. alphaAnimation.fromValue = @1.0;
    18. alphaAnimation.toValue = @0.0;
    19. alphaAnimation.removedOnCompletion = YES;
    20. }

    最后将以上动画放进一个动画群组里面,即CAAnimationGroup类型的group,并将动画添加到imageView的layer中,代码如下所示:

     
    1. - (IBAction)start:(id)sender
    2. {
    3. UIBezierPath *path = [UIBezierPath bezierPath];
    4. [self createCurve:path];
    5. //创建关键帧
    6. CAKeyframeAnimation *moveAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    7. //设置相关属性
    8. moveAnimation.path = path.CGPath;
    9. moveAnimation.removedOnCompletion = YES;
    10. //创建缩放动画
    11. CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
    12. scaleAnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
    13. scaleAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.1, 0.1, 1.0)];
    14. scaleAnimation.removedOnCompletion = YES;
    15. //创建透明度动画
    16. CABasicAnimation *alphaAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
    17. alphaAnimation.fromValue = @1.0;
    18. alphaAnimation.toValue = @0.0;
    19. alphaAnimation.removedOnCompletion = YES;
    20. //将以上动画放进一个动画组
    21. CAAnimationGroup *group = [CAAnimationGroup animation];
    22. group.animations = @[moveAnimation, scaleAnimation, alphaAnimation];
    23. group.duration = 2.0;
    24. group.delegate = self;
    25. //加入到Layer中
    26. [self.imageView.layer addAnimation:group forKey:nil];
    27. }

    实现animation的生命周期方法,当动画结束时将imageView从界面上移除,代码如下所示:

     
    1. - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
    2. {
    3. [self.imageView removeFromSuperview];
    4. }

    5.4 完整代码

    本案例中,TRAnimationViewController.m文件中的完整代码如下所示:

     
    1. #import "TRAnimationViewController.h"
    2. @interface TRAnimationViewController ()
    3. @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    4. @end
    5. @implementation TRAnimationViewController
    6. - (void)viewDidLoad
    7. {
    8. [super viewDidLoad];
    9. //设置imageView的layer属性
    10.     self.imageView.layer.cornerRadius = 8.0;
    11. self.imageView.layer.masksToBounds = YES;
    12. }
    13. //创建图片运动的曲线
    14. - (void)createCurve:(UIBezierPath *)path
    15. {
    16. [path moveToPoint:self.imageView.center];
    17. CGPoint targetPoint = CGPointMake(self.view.bounds.size.width - self.imageView.frame.size.width - 20, self.view.bounds.size.height - self.imageView.frame.size.height - 20);
    18. CGPoint control1 = CGPointMake(self.view.bounds.size.width - self.imageView.frame.size.width - 20, self.imageView.frame.origin.y);
    19. CGPoint control2 = CGPointMake(self.imageView.frame.origin.x, self.view.bounds.size.height - self.imageView.frame.size.height - 20);
    20. [path addCurveToPoint:targetPoint controlPoint1:control1 controlPoint2:control2];
    21. }
    22. - (IBAction)start:(id)sender
    23. {
    24. UIBezierPath *path = [UIBezierPath bezierPath];
    25. [self createCurve:path];
    26. //创建关键帧
    27. CAKeyframeAnimation *moveAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    28. //设置相关属性
    29. moveAnimation.path = path.CGPath;
    30. moveAnimation.removedOnCompletion = YES;
    31. //创建缩放动画
    32. CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
    33. scaleAnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
    34. scaleAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.1, 0.1, 1.0)];
    35. scaleAnimation.removedOnCompletion = YES;
    36. //创建透明度动画
    37. CABasicAnimation *alphaAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
    38. alphaAnimation.fromValue = @1.0;
    39. alphaAnimation.toValue = @0.0;
    40. alphaAnimation.removedOnCompletion = YES;
    41. //将以上动画放进一个动画组
    42. CAAnimationGroup *group = [CAAnimationGroup animation];
    43. group.animations = @[moveAnimation, scaleAnimation, alphaAnimation];
    44. group.duration = 2.0;
    45. group.delegate = self;
    46. //加入到Layer中
    47. [self.imageView.layer addAnimation:group forKey:nil];
    48. }
    49. - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
    50. {
    51. [self.imageView removeFromSuperview];
    52. }
    53. @end

    6 使用CATransform3D制作3D动画

    6.1 问题

    CATransform3D是一个结构体,是一个4x4的矩阵,用于描述一个3D图形的变形,包括旋转、缩放以及位移,本案例使用CATransform3D制作3D旋转动画,如图-8所示:

    图-8

    6.2 方案

    首先在创建好的Xcode项目的Storyboard中拖放一个ImageView控件和四个Button控件,在右边栏的检查器中设置ImageView和Button的属性,并将ImageView关联成TRRotationViewController的属性imageView。

    再将四个Button关联成TRRotationViewController的四个方法rotationX:、rotationY:、rotationZ:以及rotation:。

    然后在viewDidLoad方法中设置imageView的layer属性,将imageView设置成圆角。

    最后实现四个Button的动作方法,rotationX:实现功能围绕X轴旋转,rotationY:实现功能围绕Y轴旋转,rotationZ:实现功能围绕Z轴旋转,rotation:实现功能围绕着XYZ轴同时旋转。

    6.3 步骤

    实现此案例需要按照如下步骤进行。

    步骤一:搭建Storyboard界面

    首先在创建好的Xcode项目的Storyboard中拖放一个ImageView控件和四个Button控件,在右边栏的检查器中设置ImageView和Button的属性,并将ImageView关联成TRRotationViewController的属性imageView,代码如下所示:

     
    1. @interface TRViewController ()
    2. @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    3. @end

    Storyboard中界面完成的结果如图-9所示:

    图-9

    步骤二:实现3D旋转动画

    首先将四个Button关联成TRRotationViewController的四个方法rotationX:、rotationY:、rotationZ:以及rotation:,

    在viewDidLoad方法中设置imageView的layer属性,将imageView设置成圆角,代码如下所示:

     
    1. - (void)viewDidLoad
    2. {
    3. [super viewDidLoad];
    4. self.imageView.layer.cornerRadius = 8.0;
    5. self.imageView.layer.masksToBounds = YES;
    6. }

    然后实现四个Button的动作方法,在rotationX:方法中通过layer的transform属性,实现功能围绕X轴旋转,然后使用类似的方法实现方法rotationY:和rotationZ:,代码如下所示:

     
    1. - (IBAction)rotationX:(id)sender
    2. {
    3. //创建基本动画
    4. CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
    5. transformAnimation.fromValue = [NSValue valueWithCATransform3D:self.imageView.layer.transform];
    6. //计算目标值
    7. transformAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DRotate(self.imageView.layer.transform, M_PI, 1.0, 0, 0)];
    8. transformAnimation.duration = 3.0;
    9. //将动画添加到imageView的layer上面
    10. [self.imageView.layer addAnimation:transformAnimation forKey:nil];
    11. }
    12. - (IBAction)rotationY:(id)sender
    13. {
    14. CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
    15. transformAnimation.fromValue = [NSValue valueWithCATransform3D:self.imageView.layer.transform];
    16. transformAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DRotate(self.imageView.layer.transform, M_PI, 0.0, 1.0, 0)];
    17. transformAnimation.duration = 3.0;
    18. [self.imageView.layer addAnimation:transformAnimation forKey:nil];
    19. }
    20. - (IBAction)rotationZ:(id)sender
    21. {
    22. CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
    23. transformAnimation.fromValue = [NSValue valueWithCATransform3D:self.imageView.layer.transform];
    24. transformAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DRotate(self.imageView.layer.transform, M_PI, 0.0, 0.0, 1.0)];
    25. transformAnimation.duration = 3.0;
    26. [self.imageView.layer addAnimation:transformAnimation forKey:nil];
    27. }

    最后实现rotation:方法,该方法实现功能围绕着XYZ轴同时旋转,代码如下所示:

     
    1. - (IBAction)rotation:(id)sender
    2. {
    3. CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
    4. transformAnimation.fromValue = [NSValue valueWithCATransform3D:self.imageView.layer.transform];
    5. transformAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DRotate(self.imageView.layer.transform, M_PI, 1.0, 1.0, 1.0)];
    6. transformAnimation.duration = 3.0;
    7. transformAnimation.delegate = self;
    8. [self.imageView.layer addAnimation:transformAnimation forKey:nil];
    9. }

    实现animation的生命周期方法,当rotation动画结束时将imageView的transform属性值保持不变,从界面上移除,代码如下所示:

     
    1. - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
    2. {
    3. self.imageView.layer.transform = CATransform3DRotate(self.imageView.layer.transform, M_PI, 1.0, 1.0, 1.0);
    4. }

    6.4 完整代码

    本案例中,TRRotationViewController.m文件中的完整代码如下所示:

     
    1. #import "TRRotationViewController.h"
    2. @interface TRRotationViewController ()
    3. @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    4. @end
    5. @implementation TRRotationViewController
    6. - (void)viewDidLoad
    7. {
    8. [super viewDidLoad];
    9. self.imageView.layer.cornerRadius = 8.0;
    10. self.imageView.layer.masksToBounds = YES;
    11. }
    12. - (IBAction)rotationX:(id)sender
    13. {
    14. //创建基本动画
    15. CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
    16. transformAnimation.fromValue = [NSValue valueWithCATransform3D:self.imageView.layer.transform];
    17. //计算目标值
    18. transformAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DRotate(self.imageView.layer.transform, M_PI, 1.0, 0, 0)];
    19. transformAnimation.duration = 3.0;
    20. //将动画添加到imageView的layer上面
    21. [self.imageView.layer addAnimation:transformAnimation forKey:nil];
    22. }
    23. - (IBAction)rotationY:(id)sender
    24. {
    25. CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
    26. transformAnimation.fromValue = [NSValue valueWithCATransform3D:self.imageView.layer.transform];
    27. transformAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DRotate(self.imageView.layer.transform, M_PI, 0.0, 1.0, 0)];
    28. transformAnimation.duration = 3.0;
    29. [self.imageView.layer addAnimation:transformAnimation forKey:nil];
    30. }
    31. - (IBAction)rotationZ:(id)sender
    32. {
    33. CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
    34. transformAnimation.fromValue = [NSValue valueWithCATransform3D:self.imageView.layer.transform];
    35. transformAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DRotate(self.imageView.layer.transform, M_PI, 0.0, 0.0, 1.0)];
    36. transformAnimation.duration = 3.0;
    37. [self.imageView.layer addAnimation:transformAnimation forKey:nil];
    38. }
    39. - (IBAction)rotation:(id)sender
    40. {
    41. CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
    42. transformAnimation.fromValue = [NSValue valueWithCATransform3D:self.imageView.layer.transform];
    43. transformAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DRotate(self.imageView.layer.transform, M_PI, 1.0, 1.0, 1.0)];
    44. transformAnimation.duration = 3.0;
    45. transformAnimation.delegate = self;
    46. [self.imageView.layer addAnimation:transformAnimation forKey:nil];
    47. }
    48. - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
    49. {
    50. self.imageView.layer.transform = CATransform3DRotate(self.imageView.layer.transform, M_PI, 1.0, 1.0, 1.0);
    51. }
    52. @end
     
  • 相关阅读:
    优雅的使用Python之软件管理
    优雅的使用python之环境管理
    SpriteSheet精灵动画引擎
    【译】AS3利用CPU缓存
    走在网页游戏开发的路上(十一)
    自定义路径创建Cocos2d-x项目
    C++静态库与动态库
    C++对象模型
    超时空英雄传说2复仇魔神完全攻略&秘技
    从头写个http client(java)
  • 原文地址:https://www.cnblogs.com/52190112cn/p/5049465.html
Copyright © 2020-2023  润新知