美文网首页
iOS——动画基础

iOS——动画基础

作者: 艳晓 | 来源:发表于2017-04-13 16:51 被阅读25次

一、CAlayer层的属性

一、position和anchorPoint

1.简单介绍
CALayer有2个非常重要的属性:position和anchorPoint

 @property CGPoint position;

position用来设置CALayer在父层中的位置
以父层的左上角为原点(0, 0)

   @property CGPoint anchorPoint;

anchorPoint称为“定位点”、“锚点”
决定着CALayer身上的哪个点会在position属性所指的位置
以自己的左上角为原点(0, 0)
它的x、y取值范围都是0~1,默认值为(0.5, 0.5)

二、隐式动画

每一个UIView内部都默认关联着一个CALayer,我们可用称这个Layer为Root Layer(根层)
所有的非Root Layer,也就是手动创建的CALayer对象,都存在着隐式动画

什么是隐式动画?
当对非Root Layer的部分属性进行修改时,默认会自动产生一些动画效果
而这些属性称为Animatable Properties(可动画属性)

self.myLayer.bounds=CGRectMake(0, 0, 20, 20);

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:  (UIEvent *)event
{
    self.myLayer.bounds=CGRectMake(0, 0, 50, 50);    
}

列举几个常见的Animatable Properties:
1、bounds:用于设置CALayer的宽度和高度。修改这个属性会产生缩放动画
2、backgroundColor:用于设置CALayer的背景色。修改这个属性会产生背景色的渐变动画
3、position:用于设置CALayer的位置。修改这个属性会产生平移动画

三、基础动画

一、简单介绍

CABasicAnimation 是CAPropertyAnimation的子类

属性解析:
fromValue:keyPath相应属性的初始值
toValue:keyPath相应属性的结束值

随着动画的进行,在长度为duration的持续时间内,keyPath相应属性的值从fromValue渐渐地变为toValue

如果fillMode=kCAFillModeForwards和removedOnComletion=NO,那么在动画执行完毕后,图层会保持显示动画执行后的状态。但在实质上,图层的属性值还是动画执行前的初始值,并没有真正被改变。

比如,CALayer的position初始值为(0,0),CABasicAnimation的fromValue为(10,10),toValue为(100,100),虽然动画执行完毕后图层保持在(100,100)这个位置,实质上图层的position还是为(0,0)

平移动画

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    // 基础动画
    //1.创建核心动画
    //    CABasicAnimation *anima=[CABasicAnimation animationWithKeyPath:<#(NSString *)#>]
    CABasicAnimation *anima=[CABasicAnimation animation];
    //1.1告诉系统要执行什么样的动画
    anima.keyPath=@"position";
   //设置通过动画,将layer从哪儿移动到哪儿
    anima.fromValue=[NSValue valueWithCGPoint:CGPointMake(0, 0)];
    anima.toValue=[NSValue valueWithCGPoint:CGPointMake(200, 300)]; 
    //1.2设置动画执行完毕之后不删除动画
    anima.removedOnCompletion=NO;
    //1.3设置保存动画的最新状态
    anima.fillMode=kCAFillModeForwards;
    // 1.4设置代理:设置动画的代理,可以监听动画的执行过程,这里设置控制器为代理
    anima.delegate=self;
    //2.添加核心动画到layer
    [self.myLayer addAnimation:anima forKey:nil];
}

缩放动画

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    // 基础动画
    //1.创建核心动画
    //    CABasicAnimation *anima=[CABasicAnimation animationWithKeyPath:<#(NSString *)#>]
    CABasicAnimation *anima=[CABasicAnimation animation];
    //1.1告诉系统要执行什么样的动画
    anima.keyPath=@"bounds";
    //设置通过动画,将layer从哪儿移动到哪儿
    anima.fromValue=[NSValue valueWithCGRect:CGRectMake(0, 0, 20, 20)];
    anima.toValue=[NSValue valueWithCGRect:CGRectMake(0, 0, 50, 50)];
    //1.2设置动画执行完毕之后不删除动画
    anima.removedOnCompletion=NO;
    //1.3设置保存动画的最新状态
    anima.fillMode=kCAFillModeForwards;
    anima.repeatCount = 10;// 动画重复次数
    anima.duration = 1;// 执行一次动画时间
    //2.添加核心动画到layer
    [self.myLayer addAnimation:anima forKey:nil];
}

代码说明:
1、设置的keyPath是@"position",说明要修改的是CALayer的position属性,也就是会执行平移动画
2、fromValue、toValue属性接收的时id类型的参数,因此并不能直接使用CGRect这种结构体类型,而是要先包装成NSValue对象后再使用。
3、 默认情况下,动画执行完毕后,动画会自动从CALayer上移除,CALayer又会回到原来的状态。为了保持动画执行后的状态,可以加入第48,50行代码
4、byValue和toValue的区别,前者是在当前的位置上增加多少,后者是到指定的位置。

旋转动画

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    // 旋转动画
    //1.创建动画
    CABasicAnimation *anima=[CABasicAnimation animationWithKeyPath:@"transform"];
    //1.1设置动画执行时间
    anima.duration=2.0;
    //1.2修改属性,执行动画
    anima.toValue=[NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2+M_PI_4, 1, 1, 0)];
    // 可以通过transform(KVC)的方式来进行设置。
     anima.toValue=[NSValue valueWithCATransform3D:CATransform3DMakeTranslation(0, 100, 1)];
    //1.3设置动画执行完毕后不删除动画
    anima.removedOnCompletion=NO;
    //1.4设置保存动画的最新状态
    anima.fillMode=kCAFillModeForwards;
    //2.添加动画到layer
    [self.myLayer addAnimation:anima forKey:nil];
}

如果要让图形以2D的方式旋转,只需要把CATransform3DMakeRotation在z方向上的值改为1即可。

anima.toValue=[NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2+M_PI_4, 1, 1, 0)];

四、关键帧动画

一、简单介绍

CAKeyframeAnimation是CApropertyAnimation的子类,跟CABasicAnimation的区别是:CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue),而CAKeyframeAnimation会使用一个NSArray保存这些数值

属性解析:

values:就是上述的NSArray对象。里面的元素称为”关键帧”(keyframe)。动画对象会在指定的时间(duration)内,依次显示values数组中的每一个关键帧

path:可以设置一个CGPathRef\CGMutablePathRef,让层跟着路径移动。path只对CALayer的anchorPoint和position起作用。如果你设置了path,那么values将被忽略

keyTimes:可以为对应的关键帧指定对应的时间点,其取值范围为0到1.0,keyTimes中的每一个时间值都对应values中的每一帧.当keyTimes没有设置的时候,各个关键帧的时间是平分的

说明:CABasicAnimation可看做是最多只有2个关键帧的CAKeyframeAnimation

二、代码示例

- (void)viewDidLoad {
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor blueColor];
    UIView * contentView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    contentView.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:contentView];
    self.contentView = contentView;
   // 停止按钮
    UIButton * stopBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    stopBtn.backgroundColor = [UIColor orangeColor];
    stopBtn.frame = CGRectMake(10, 10,100 , 30);
    [stopBtn setTitle:@"停止" forState:UIControlStateNormal];
    [self.view addSubview:stopBtn];
    [stopBtn addTarget:self action:@selector(stopBtnClicked:) forControlEvents:UIControlEventTouchUpInside];

}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    //1.创建核心动画
    CAKeyframeAnimation *keyAnima=[CAKeyframeAnimation animation];
    //平移
    keyAnima.keyPath=@"position";
    //1.1告诉系统要执行什么动画
    NSValue *value1=[NSValue valueWithCGPoint:CGPointMake(100, 100)];
    NSValue *value2=[NSValue valueWithCGPoint:CGPointMake(200, 100)];
    NSValue *value3=[NSValue valueWithCGPoint:CGPointMake(200, 200)];
    NSValue *value4=[NSValue valueWithCGPoint:CGPointMake(100, 200)];
    NSValue *value5=[NSValue valueWithCGPoint:CGPointMake(100, 100)];
    keyAnima.values=@[value1,value2,value3,value4,value5];
    //1.2设置动画执行完毕后,不删除动画
    keyAnima.removedOnCompletion=NO;
    //1.3设置保存动画的最新状态
    keyAnima.fillMode=kCAFillModeForwards;
    //1.4设置动画执行的时间
    keyAnima.duration=4.0;
    //1.5设置动画的节奏
    keyAnima.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    //设置代理,开始—结束
    keyAnima.delegate=self;
    keyAnima.repeatCount = 10;
    //2.添加核心动画
    [self.contentView.layer addAnimation:keyAnima forKey:@"demoAni"];
}

-(void)animationDidStart:(CAAnimation *)anim
{

}

-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{

}

-(void)stopBtnClicked:(UIButton *)sender
{
   // 动画停止
    [self.contentView.layer removeAnimationForKey:@"demoAni"];
}

五、组动画

CAAnimation的子类,可以保存一组动画对象,将CAAnimationGroup对象加入层后,组中所有动画对象可以同时并发运行

属性解析:

animations:用来保存一组动画对象的NSArray

默认情况下,一组动画对象是同时运行的,也可以通过设置动画对象的beginTime属性来更改动画的开始时间

- (void)viewDidLoad {
   [super viewDidLoad];
   // Do any additional setup after loading the view.
   self.view.backgroundColor = [UIColor blueColor];
   UIView * contentView = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 100, 100)];
   contentView.backgroundColor = [UIColor whiteColor];
   [self.view addSubview:contentView];
   self.contentView = contentView;

}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:  (UIEvent *)event
{
   CABasicAnimation * a1 = [CABasicAnimation animation];
   a1.keyPath = @"transform.translation.y";
   a1.toValue = @(100);

      // 缩放动画
    CABasicAnimation *a2 = [CABasicAnimation animation];
   a2.keyPath = @"transform.scale";
   a2.toValue = @(0.0);

   // 旋转动画
   CABasicAnimation *a3 = [CABasicAnimation animation];
   a3.keyPath = @"transform.rotation";
   a3.toValue = @(M_PI_2);
   // 组动画
   CAAnimationGroup *groupAnima = [CAAnimationGroup animation];
   groupAnima.animations = @[a1, a2, a3];
   //设置组动画的时间
   groupAnima.duration = 2;
   groupAnima.fillMode = kCAFillModeForwards;
   groupAnima.removedOnCompletion = NO;
   [self.contentView.layer addAnimation:groupAnima forKey:nil];
}

六、转场动画

CATransition 是CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。iOS比Mac OS X的转场动画效果少一点

UINavigationController就是通过CATransition实现了将控制器的视图推入屏幕的动画效果

属性解析:

type:动画过渡类型
subtype:动画过渡方向
startProgress:动画起点(在整体动画的百分比)
endProgress:动画终点(在整体动画的百分比)

@interface TransitionAniViewController ()<CAAnimationDelegate>
@property(nonatomic,assign) int index;
@property (nonatomic, strong) UIImageView * contentView;
@end

@implementation TransitionAniViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.index=1;
    UIButton * nextBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    nextBtn.backgroundColor = [UIColor orangeColor];
    nextBtn.frame = CGRectMake(10, 50,100 , 30);
    [nextBtn setTitle:@"下一个" forState:UIControlStateNormal];
    [self.view addSubview:nextBtn];
    [nextBtn addTarget:self action:@selector(nextBtnClicked:) forControlEvents:UIControlEventTouchUpInside];

    UIButton * preBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    preBtn.backgroundColor = [UIColor orangeColor];
    preBtn.frame = CGRectMake(10, 10,100 , 30);
    [preBtn setTitle:@"上一个" forState:UIControlStateNormal];
    [self.view addSubview:preBtn];
    [preBtn addTarget:self action:@selector(preBtnClicked:) forControlEvents:UIControlEventTouchUpInside];

    UIImageView * contentView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];
    contentView.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:contentView];
    self.contentView = contentView;

}

-(void)preBtnClicked:(UIButton *)sender
{
    self.index--;
    if (self.index<1) {
        self.index=7;
    }
    self.contentView.image=[UIImage imageNamed: [NSString stringWithFormat:@"%d.jpg",self.index]];
    //创建核心动画
    CATransition *ca=[CATransition animation];
    //告诉要执行什么动画
    //设置过度效果
    ca.type=@"cube";
    //设置动画的过度方向(向左)
    ca.subtype=kCATransitionFromLeft;
    //设置动画的时间
    ca.duration=2.0;
    //添加动画
    [self.contentView.layer addAnimation:ca forKey:nil];
    
}
-(void)nextBtnClicked:(UIButton *)sender
{
    self.index++;
    if (self.index>7) {
        self.index=1;
    }
    self.contentView.image=[UIImage imageNamed: [NSString stringWithFormat:@"%d.jpg",self.index]];
    //1、创建核心动画
    CATransition *ca=[CATransition animation];
    //1.1 告诉要执行什么动画
    //1.2 设置过渡效果
//    过渡效果有四种`fade', `moveIn', `push' and `reveal'
    ca.type=@"cube";
    //1.3 设置动画的过度方向(向左)
    ca.subtype=kCATransitionFromRight;
    //1.4 设置动画的时间
    ca.duration=2.0;
    //1.5设置动画的起点
//    ca.startProgress=0.5;
    //2、添加动画
    [self.contentView.layer addAnimation:ca forKey:nil];

}

七、UIView动画

UIKit直接将动画集成到UIView类中,当内部的一些属性发生改变时,UIView将为这些改变提供动画支持

执行动画所需要的工作由UIView类自动完成,但仍要在希望执行动画时通知视图,为此需要将改变属性的代码放在[UIView beginAnimations:nil context:nil]和[UIView commitAnimations]之间

常见方法解析:

+ (void)setAnimationDelegate:(id)delegate    

设置动画代理对象,当动画开始或者结束时会发消息给代理对象

+ (void)setAnimationWillStartSelector:(SEL)selector   

当动画即将开始时,执行delegate对象的selector,并且把beginAnimations:context:中传入的参数传进selector

+ (void)setAnimationDidStopSelector:(SEL)selector  

当动画结束时,执行delegate对象的selector,并且把beginAnimations:context:中传入的参数传进selector

+ (void)setAnimationDuration:(NSTimeInterval)duration   

动画的持续时间,秒为单位

+ (void)setAnimationDelay:(NSTimeInterval)delay 

动画延迟delay秒后再开始

+ (void)setAnimationStartDate:(NSDate *)startDate   

动画的开始时间,默认为now

+ (void)setAnimationCurve:(UIViewAnimationCurve)curve  

动画的节奏控制

+ (void)setAnimationRepeatCount:(float)repeatCount 

动画的重复次数

+ (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses 

如果设置为YES,代表动画每次重复执行的效果会跟上一次相反

+ (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache  

设置视图view的过渡效果, transition指定过渡类型, cache设置YES代表使用视图缓存,性能较好

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor blueColor];
    UIView * contentView = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 100, 100)];
    contentView.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:contentView];
    self.contentView = contentView;

}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    NSLog(@"动画执行之前的位置:%@",NSStringFromCGPoint(self.contentView.center));
    //首尾式动画
    [UIView beginAnimations:nil context:nil];
    //设置动画执行时间
    [UIView setAnimationDuration:2.0];
   [UIView setAnimationRepeatCount:3];
    //设置代理
    [UIView setAnimationDelegate:self];
    //设置动画执行完毕调用的事件
    [UIView setAnimationDidStopSelector:@selector(didStopAnimation)];
    self.contentView.center=CGPointMake(200, 300);
    [UIView commitAnimations];
}
-(void)didStopAnimation{
    NSLog(@"动画执行之后的位置:%@",NSStringFromCGPoint(self.contentView.center));
}

八、UIView封装的动画与CALayer动画的对比

使用UIView和CALayer都能实现动画效果,但是在真实的开发中,一般还是主要使用UIView封装的动画,而很少使用CALayer的动画。

CALayer核心动画与UIView动画的区别:
UIView封装的动画执行完毕之后不会反弹。即如果是通过CALayer核心动画改变layer的位置状态,表面上看虽然已经改变了,但是实际上它的位置是没有改变的。

九、block动画

1.简单说明
+ (void)animateWithDuration:(NSTimeInterval)duration delay:
(NSTimeInterval)delay options:(UIViewAnimationOptions)options
animations:(void (^)(void))animations completion:(void (^)
(BOOL finished))completion

参数解析:
duration:动画的持续时间
delay:动画延迟delay秒后开始
options:动画的节奏控制
animations:将改变视图属性的代码放在这个block中
completion:动画结束后,会自动调用这个block

转场动画

+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration
 options:(UIViewAnimationOptions)options animations:(void (^)(void))animations 
completion:(void (^)(BOOL finished))completion

参数解析:
duration:动画的持续时间
view:需要进行转场动画的视图
options:转场动画的类型
animations:将改变视图属性的代码放在这个block中
completion:动画结束后,会自动调用这个block

+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView
 duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options 
completion:(void (^)(BOOL finished))completion

方法调用完毕后,相当于执行了下面两句代码:

// 添加toView到父视图
[fromView.superview addSubview:toView]; 
// 把fromView从父视图中移除
[fromView removeFromSuperview];

参数解析:

duration:动画的持续时间
options:转场动画的类型
animations:将改变视图属性的代码放在这个block中
completion:动画结束后,会自动调用这个block

2.代码示例

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
   //block代码块动画
       [UIView transitionWithView:self.customView duration:3.0 options:0 animations:^{
           //执行的动画
          NSLog(@"动画开始执行前的位置:%@",NSStringFromCGPoint(self.customView.center));
           self.customView.center=CGPointMake(200, 300);
       } completion:^(BOOL finished) {
           //动画执行完毕后的首位操作
           NSLog(@"动画执行完毕");
           NSLog(@"动画执行完毕后的位置:%@",NSStringFromCGPoint( self.customView.center));
      }];
 }

提示:self.customView.layer.position和self.customView.center等价,因为position的默认值为(0.5,0.5)。

十、补充

1.UIImageView的帧动画

UIImageView可以让一系列的图片在特定的时间内按顺序显示

相关属性解析:
animationImages:要显示的图片(一个装着UIImage的NSArray)
animationDuration:完整地显示一次animationImages中的所有图片所需的时间
animationRepeatCount:动画的执行次数(默认为0,代表无限循环)

相关方法解析:
- (void)startAnimating; 开始动画

- (void)stopAnimating;  停止动画

- (BOOL)isAnimating;  是否正在运行动画

2.UIActivityIndicatorView

是一个旋转进度轮,可以用来告知用户有一个操作正在进行中,一般用initWithActivityIndicatorStyle初始化

方法解析:

- (void)startAnimating; 开始动画

- (void)stopAnimating;  停止动画

- (BOOL)isAnimating;  是否正在运行动画

UIActivityIndicatorViewStyle有3个值可供选择:

UIActivityIndicatorViewStyleWhiteLarge //大型白色指示器
UIActivityIndicatorViewStyleWhite //标准尺寸白色指示器
UIActivityIndicatorViewStyleGray //灰色指示器,用于白色背景

相关文章

  • iOS 动画基础总结篇

    iOS 动画基础总结篇 iOS 动画基础总结篇

  • iOS动画

    iOS动画分为基础动画和核心动画 本文发布在http://he8090.cn/2016/07/18/iOS动画/...

  • iOS核心动画总结

    基础概念 iOS图形架构 核心动画是 iOS 和 MacOS 上的图形渲染和动画基础结构,用于为应用的视图和...

  • 1. 控制动画

    《iOS编程》第27章 控制动画 学习笔记 基础动画 关键帧动画

  • 动画

    Core Animation iOS 动画主要是指Core Animation框架, 基础动画(CABasicAn...

  • 动画(二)

    这期动画是对基础动画的一个小结。动画的基本属性请看:iOS动画一 说到总结基础动画再总结下属性吧。想要的动画的动画...

  • iOS Core Animation (一) 基础动画

    iOS核心动画Core Animation分为几类:基础动画、关键帧动画、动画组、转场动画。关系大致如下图: CA...

  • 核心动画一览

    基础 核心动画是 iOS 和 MacOS 上的图形渲染和动画基础结构,用于为应用的视图和其他视觉元素设置动画。 核...

  • iOS动画的基础知识

    前言 相信大部份iOS开发者在实现一些基础动画时会感叹动画API的简便及动画效果的真实性,动画是iOS的一大...

  • iOS动画不响应点击的问题

    iOS动画分为显性动画和隐性动画两种。 显示动画动画分为几类:基础动画、关键帧动画、动画组、转场动画。各个类的关系...

网友评论

      本文标题:iOS——动画基础

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