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

动画(Animation) 、 高级动画(Core Animation)的更多相关文章

  1. iOS动画-从UIView到Core Animation

    首先,介绍一下UIView相关的动画. UIView普通动画: [UIView beginAnimations: context:]; [UIView commitAnimations]; 动画属性设 ...

  2. 简析iOS动画原理及实现——Core Animation

    本文转载至 http://www.tuicool.com/articles/e2qaYjA 原文  https://tech.imdada.cn/2016/06/21/ios-core-animati ...

  3. IOS动画(Core Animation)总结 (参考多方文章)

    一.简介 iOS 动画主要是指Core Animation框架.官方使用文档地址为:Core Animation Guide. Core Animation是IOS和OS X平台上负责图形渲染与动画的 ...

  4. 核心动画——Core Animation

    一. CALayer (一). CALayer简单介绍 在iOS中,你能看得见摸得着的东西基本上都是UIView,比方一个button.一个文本标签.一个文本输入框.一个图标等等.这些都是UIView ...

  5. Core Animation编程指南

    本文是<Core Animation Programming Guide>2013-01-28更新版本的译文.本文略去了原文中关于OS X平台上Core Animation相关内容.因为原 ...

  6. Core Animation学习总结

    文件夹: The Layer Beneath The Layer Tree(图层树) The Backing Image(寄宿层) Layer Geometry(图层几何学) Visual Effec ...

  7. 说说Core Animation

    前言 本次分享将从以下方面进行展开: 曾被面试官问倒过的问题:层与视图的关系 CALayer类介绍及层与视图的关系 CAShapeLayer类介绍 UIBezierPath贝塞尔曲线讲解 CoreAn ...

  8. Core Animation Manages Your App’s Content

    Core Animation 是对现有图片的操作函数. https://developer.apple.com/library/content/documentation/Cocoa/Conceptu ...

  9. iOS动画1 — UIView动画

    iOS动画基础是Core Animation核心动画.Core Animation是iOS平台上负责图形渲染与动画的基础设施.由于核心动画的实现比较复杂,苹果提供了实现简单动画的接口—UIView动画 ...

  10. iOS核心动画以及UIView动画的介绍

    我们看到很多App带有绚丽狂拽的特效,别出心裁的控件设计,很大程度上提高了用户体验,在增加了实用性的同时,也赋予了app无限的生命力.这些华丽的效果很多都是基于iOS的核心动画原理实现的,本文介绍一些 ...

随机推荐

  1. 企业级的响应式设计(Responsive design at enterprise level)译

    导言 响应式设计是现在人们谈论的热点,但如何部署,特别是在有多种设备的大型项目中如何组织响应式设计,响应式设计和可伸缩性(Scalable)有什么区别?这都是需要解决的难题. 优化用户经验——Opti ...

  2. Linux创建LVM

    ###########format disk############ 格式化磁盘,将其SystemId修改为8e fdisk /dev/sdb n p 1 [enter] [enter] t 8e w ...

  3. [示例]NSDictionary编程题-字典的排序应用(iOS4班)

    代码: #import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepo ...

  4. 一天完成把PC网站改为自适应!原来这么简单!

    http://www.webkaka.com/blog/archives/how-to-modify-a-web-page-to-be-responsive.html 一天完成把PC网站改为自适应!原 ...

  5. TaskTracker启动过程源码级分析

    TaskTracker也是作为一个单独的JVM来运行的,其main函数就是TaskTracker的入口函数,当运行start-all.sh时,脚本就是通过SSH运行该函数来启动TaskTracker的 ...

  6. [转载]Android 异步加载解决方案

    2013-12-25 11:15:47 Android 异步加载解决方案,转载自: http://www.open-open.com/lib/view/open1345017746897.html 请 ...

  7. MATLAB 函数

    MATLAB函数大全 1.常见 http://wenku.baidu.com/link?url=tPpwD7Ox_1sG-SQv_XdYszBAPY9LX_Zb_dde_5JeOiu7RwN_i14X ...

  8. IT公司100题-17-第一个只出现一次的字符

    问题描述: 在一个字符串中找到第一个只出现一次的字符.例如输入asdertrtdsaf,输出e.   分析: 最简单的方法是直接遍历,时间复杂度为O(n^2). 进一步思考: 字符串中的字符,只有25 ...

  9. Android 时间戳的转换

    在Android应用中,经常会碰到后台的时间是时间戳而现实的需要今天什么时候,昨天什么时候,就像微博的时间显示一样.现在我上一个把时间戳转换的代码: public static String getT ...

  10. mybatis多对一关联的两种方式

    第一个种是Address找到自己的user_id,扔给User,让User自己去再查一次,即使在有缓存的前提下,每遇到一个新的user_id,就会查一次,对比hibernate的话,相当于多对一eag ...