UIView动画与核心动画的对比使用

核心动画的继承关系图


UIView动画与核心动画的对比使用_第1张图片
核心动画的继承关系

一、基础动画

改变位移、透明度、缩放、旋转、背景色改变等行为产生的动画,系统CALyer的核心动画的有些Api在改变指定属性后默认就能产生动画,只有非root layer才有隐式动画,进入头文件查看凡是有标注Animatable的Api默认都可以产生动画,例如下面的position属性:

UIView动画与核心动画的对比使用_第2张图片
CALyer的position属性

下面分别使用三种方式实现位移动画为样例,这几种虽然效果都是一样的,但是使用不同的系统API会有不同的动画属性和状态;其他的动画用法都一样,只需要修改keyPathfromValuetoValue的值即可。

UIView动画与核心动画的对比使用_第3张图片
平移动画
  1. 实现方式一:使用CAlayer的核心动画实现方式
//使用CABasicAnimation创建基础动画
-(void)testAnimation
{
        CABasicAnimation *anima = [CABasicAnimation animation];
        anima.keyPath = @"position";  //整体平移
        //anima.keyPath = @"position.x"; //则x方向平移多少
        //anima.keyPath = @"transform.translation; //也是平移动画
    
        //动画从一个点执行到另一个点,记得这里接收的值要包装成 `NSValue` 。。。
        anima.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, SCREEN_HEIGHT/2-75)];
        anima.toValue = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH, SCREEN_HEIGHT/2-75)];

        //在原来值的基础上增加多少
        //anima.byValue =@(80.0);
    
        //动画执行时间
        anima.duration = 1.0f;
    
        //设置动画保持结束的状态,注意:实际上图层的属性值还是动画执行前的初始值,并没有真正被改变。
        anima.fillMode = kCAFillModeForwards;
        anima.removedOnCompletion = NO;

        //动画执行次数,`MAXFLOAT`表示最大次数。
        anima.repeatCount = MAXFLOAT;

        //设置当前为实例为动画的代理,可监听动画的开始和结束。
        anima.delegate = self;
    
        //控制动画执行的速度节奏,具体有哪些值可进入头文件查看。
        anima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
        [_demoView.layer addAnimation:anima forKey:@"positionAnimation"];
 }

1.1 CAPropertyAnimationKeyPath的值可以有以下这些

transform.scale = 比例转换
transform.rotation = 旋转
opacity = 透明度
margin = 边距
position = 位移
backgroundColor = 背景颜色
cornerRadius = 圆角
borderWidth = 边框宽度
bounds = 位置,体积
contents = 内容
contentsRect = 面积
frame = 位置,体积
hidden = 是否隐藏
mask = 任务
masksToBounds
shadowColor = 阴影颜色
shadowOffset = 阴影偏移
shadowOpacity = 阴影透明
shadowRadius = 阴影半径

1.2 这里的keyPath能设置的值在系统API中的有这些,可以在Xcode的苹果官方文档中键入关键字CATransform3D value key paths搜索能看到详细的用法:

UIView动画与核心动画的对比使用_第4张图片
苹果官方文档: CATransform3D value key paths

2 . 实现方式二: 使用UIView的Block动画实现方式

//使用UIView Animation 代码块调用
-(void)testAnimation2
{
        [UIView animateWithDuration:1.0f animations:^{
            //平移动画
            _demoView.transform = CGAffineTransformMakeTranslation(SCREEN_WIDTH, SCREEN_HEIGHT/2-50);
        } completion:^(BOOL finished) {
            //复原transform值,复原也会使控件位置复原
            _demoView.transform = CGAffineTransformIdentity;
        }];
}

3 . 实现方式三: 使用UIVew的【begin commit 】这种用法在开发中使用较少

//使用UIView [begin,commit]模式
-(void)testAnimation3
{
      _demoView.frame = CGRectMake(0, SCREEN_HEIGHT/2-50, 50, 50);
      [UIView beginAnimations:nil context:nil];
      [UIView setAnimationDuration:1.0f];
      _demoView.frame = CGRectMake(SCREEN_WIDTH, SCREEN_HEIGHT/2-50, 50, 50);
      [UIView commitAnimations];
}

** 对比总结:** 这里三种方式都可以实现相同的动画,不同的实现方式有不同的好处,在我们项目中可以根据自己的实际需求选择相应的实现方式,建议是:在对UI控件的大小位置有没有要求的情况下我们推荐使用CALayer的核心动画实现,没有要求的可以使用UIViewBlock方式实现;而核心动画都是后台执行的动画它不会阻塞UI线程,能执行很多绚丽的组合动画,但也有一些弊端,比如动画在页面之间切换、前后台的切换后动画有可能会停止,这些弊端在使用UIViewBlock方式就不会有这样的问题,相应的UIView动画能执行的动画类型相对少很多。

二、帧动画

关键帧动画CAKeyframeAnimation类继承于CAPropertyAnimation类,属于属性动画的范畴,它能做一组相同的动画,因此它有一个values数组Api属性,数组中都是每个关键帧所做的动画值,常见的关键帧动画比如做平移、图标抖动等动画。

UIView动画与核心动画的对比使用_第5张图片
关键帧动画

1 . 一组移动位置的 关键帧动画用法例子:

/**
 *  关键帧动画
 */
-(void)keyFrameAnimation{
    CAKeyframeAnimation *anima = [CAKeyframeAnimation animation];
    anima.keyPath = @"position";  //关键帧平移动画
    NSValue *value0 = [NSValue valueWithCGPoint:CGPointMake(0, SCREEN_HEIGHT/2-50)];
    NSValue *value1 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH/3, SCREEN_HEIGHT/2-50)];
    NSValue *value2 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH/3, SCREEN_HEIGHT/2+50)];
    NSValue *value3 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH*2/3, SCREEN_HEIGHT/2+50)];
    NSValue *value4 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH*2/3, SCREEN_HEIGHT/2-50)];
    NSValue *value5 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH, SCREEN_HEIGHT/2-50)];
    //每个动画的值,需要包装成`NSValue`类型
    anima.values = [NSArray arrayWithObjects:value0,value1,value2,value3,value4,value5, nil];
    anima.duration = 2.0f;
    //设置动画的节奏
    anima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    //设置代理,可以检测动画的开始和结束
    anima.delegate = self;
    [_demoView.layer addAnimation:anima forKey:@"keyFrameAnimation"];
}

2 . 关键帧动画CAKeyframeAnimation类还有一个CGPathRef类型的path属性,因此也可以做一些围绕路径的帧动画,例如下面的path转圈动画:

UIView动画与核心动画的对比使用_第6张图片
`path`转圈动画

/**
 *  path动画
 */
-(void)pathAnimation{
    CAKeyframeAnimation *anima = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(SCREEN_WIDTH/2-100, SCREEN_HEIGHT/2-100, 200, 200)];
    anima.path = path.CGPath;
    anima.duration = 2.0f;
    [_demoView.layer addAnimation:anima forKey:@"pathAnimation"];
}

三、转场动画

UIView动画与核心动画的对比使用_第7张图片

1 . 实现方式一:使用transitionFromView: toView: duration:... 此Api的转过渡场动画是发生在两个View之间, 官方文档上明确提出: 在动画完毕之后, fromView会出从父视图上被移除, 而 toView 会被添加到 fromView 所在的父视图,因此在做系统的反转动画时,需要一个自定义的父视图View,如果直接使用控制器的View,则会把当前控制器的View一并反转。 代码例子如下:

- (void)transitionAnimation1
{
    self.goingToFront = !self.goingToFront;
    
    UIView *fromView = self.goingToFront ? self.imageView1 : self.imageView2;
    UIView *toView = self.goingToFront ? self.imageView2 : self.imageView1;
    
      UIViewAnimationOptions transitionDirection = 
    self.goingToFront ? UIViewAnimationOptionTransitionFlipFromRight : UIViewAnimationOptionTransitionFlipFromLeft;

    [UIView transitionFromView:fromView
                        toView:toView
                      duration:0.5
                       options:transitionDirection
                    completion:^(BOOL finished) {
                        NSLog(@"动画完成\n===%@\n===%@\n===%@",self.imageView1,self.imageView2,self.contentView);
                    }];
}

2 . 实现方式二:使用transitionWithView: duration:... 此Api这种类型的转场动画是发生在一个View之间的过渡转场,因为参数就只传入一个UIView . 代码例子如下:

- (void) transitionAnimation2
{
        self.goingToFront = !self.goingToFront;

        UIViewAnimationOptions transitionDirection = 
     self.goingToFront ? UIViewAnimationOptionTransitionFlipFromRight : UIViewAnimationOptionTransitionFlipFromLeft;

        [UIView transitionWithView:self.contentView
                      duration:0.5
                       options:transitionDirection
                    animations:^{
                        [self.contentView exchangeSubviewAtIndex:0 withSubviewAtIndex:1];
        } completion:^(BOOL finished) {
            NSLog(@"动画完成");
    }];
}

3 . 实现方式三:使用CATransition 此Api的核心动画 . 代码例子如下:

-(void) transitionAnimation3{
    CATransition *anima = [CATransition animation];
    //设置动画的类型    
    anima.type = kCATransitionPush;
    //设置动画的方向
    anima.subtype = kCATransitionFromRight; 
    //动画持续时间
    anima.duration = 1.0f;    
    //设置动画起始点
    anima.startProgress = 0.3;
    //设置动画结束点
    anima.endProgress = 0.8;
    [_demoView.layer addAnimation:anima forKey:@"pushAnimation"];
}

3.1 这里的anima.type动画的类型: 可选的动画类型非常有限,系统默认提供了四个值:

kCATransitionFade;    //逐渐消失
kCATransitionMoveIn;  //逐渐进入
kCATransitionPush;    //类似导航控制器的push动画
kCATransitionReveal;  //逐渐移出

3.2 除系统默认提供的动画类型之外,还有一些私有Api的动画类型,不过使用这些私有Api会有上架被拒风险,具体的类型如下:

    Fade = 1,                   //淡入淡出
    Push,                       //推挤
    Reveal,                     //揭开
    MoveIn,                     //覆盖
    Cube,                       //立方体
    SuckEffect,                 //吮吸
    OglFlip,                    //翻转
    RippleEffect,               //波纹
    PageCurl,                   //翻页
    PageUnCurl,                 //反翻页
    CameraIrisHollowOpen,       //开镜头
    CameraIrisHollowClose,      //关镜头
    CurlDown,                   //下翻页
    CurlUp,                     //上翻页
    FlipFromLeft,               //左翻转
    FlipFromRight,              //右翻转

3.3 anima.subtype动画的方向:系统默认也提供了四个值:

kCATransitionFromRight;     //从右边开始
kCATransitionFromLeft;      //从左边开始
kCATransitionFromTop;       //从上面开始
kCATransitionFromBottom;    //从下面开始

四、组合动画

CAAnimation的子类,可以保存一组动画对象,将CAAnimationGroup对象加入层后,组中所有动画对象可以同时并发运行。重要属性:animations用来保存一组动画对象的NSArray

UIView动画与核心动画的对比使用_第8张图片
组合动画

一个同时执行的组合动画例子:

/**
 *  组合动画
 */
-(void)groupAnimation{
    //位移动画
    CAKeyframeAnimation *anima1 = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    NSValue *value0 = [NSValue valueWithCGPoint:CGPointMake(0, SCREEN_HEIGHT/2-50)];
    NSValue *value1 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH/3, SCREEN_HEIGHT/2-50)];
    NSValue *value2 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH/3, SCREEN_HEIGHT/2+50)];
    NSValue *value3 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH*2/3, SCREEN_HEIGHT/2+50)];
    NSValue *value4 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH*2/3, SCREEN_HEIGHT/2-50)];
    NSValue *value5 = [NSValue valueWithCGPoint:CGPointMake(SCREEN_WIDTH, SCREEN_HEIGHT/2-50)];
    anima1.values = [NSArray arrayWithObjects:value0,value1,value2,value3,value4,value5, nil];
    
    //缩放动画
    CABasicAnimation *anima2 = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    anima2.fromValue = [NSNumber numberWithFloat:0.8f];
    anima2.toValue = [NSNumber numberWithFloat:2.0f];
    
    //旋转动画
    CABasicAnimation *anima3 = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
    anima3.toValue = [NSNumber numberWithFloat:M_PI*4];
    
    //组动画
    CAAnimationGroup *groupAnimation = [CAAnimationGroup animation];
    groupAnimation.animations = [NSArray arrayWithObjects:anima1,anima2,anima3, nil];
    groupAnimation.duration = 4.0f;
    
    [_demoView.layer addAnimation:groupAnimation forKey:@"groupAnimation"];
}

你可能感兴趣的:(UIView动画与核心动画的对比使用)