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

核心动画的继承关系图


核心动画的继承关系

一、基础动画

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

CALyer的position属性

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

平移动画
  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;

        //设置当前为实例为动画的代理<CAAnimationDelegate>,可监听动画的开始和结束。
        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搜索能看到详细的用法:

苹果官方文档: 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属性,数组中都是每个关键帧所做的动画值,常见的关键帧动画比如做平移、图标抖动等动画。

关键帧动画

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转圈动画:

`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"];
}

三、转场动画

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

组合动画

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

/**
 *  组合动画
 */
-(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"];
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容

  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥ios动画全貌。在这里你可以看...
    每天刷两次牙阅读 8,471评论 6 30
  • 在iOS实际开发中常用的动画无非是以下四种:UIView动画,核心动画,帧动画,自定义转场动画。 1.UIView...
    请叫我周小帅阅读 3,082评论 1 23
  • 一、简介 Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,使用它能做出非常炫丽...
    莦婼姑娘阅读 956评论 0 4
  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌。在这里你可以看...
    F麦子阅读 5,104评论 5 13
  • 概览 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌。在这里你...
    Yiart阅读 3,799评论 3 34