参考:https://zsisme.gitbooks.io/ios-/content/

前面的文章动画基础--基于Core Animation(1),动画基础--基于Core Animation(2)提到了图层的基本概念以及可动画参数几何学等知识。

本片文章将继续探讨更加深入的动画知识。

本章代码:https://github.com/xufeng79x/defaultAnim

前面已经两篇文章已经就图层的概念和几何学和效果表现,变换等左列介绍。

在前面的两篇文章中大部分采用了视图自带的backing 图层进行讲解,本身这个图层是禁止动画效果的。所以在前面的文章中很少看到明显的

动画,在接下来的总结文章中将介绍隐式动画和显示动画。

首先需要总结的是:

  1.视图的本身是没有动画概念的,它的动画的接口和效果的产生其实是对于其内部图层的处理。

  2.不是所有图层的属性都具有动画效果,只有可动画属性才能具有动画效果。

  以下为常用的图层可动画属性

  

1.隐式动画

 简单的隐式动画:

  当你改变CALayer的一个可做动画的属性,它并不能立刻在屏幕上体现出来。相反,它是从先前的值平滑过渡到新的值。这一切都是默认的行为,你不需要做额外的操作。

  隐式动画在图层中是默认开启的,如果不需要隐式动画则需要主动去关闭它。

#pragma 测试简单动画
-(void)testSampleAnimation
{

    mySampleLayer = [CALayer layer];
    mySampleLayer.backgroundColor = [UIColor blackColor].CGColor;
    mySampleLayer.frame = CGRectMake(, , , );
    [self.view.layer addSublayer:mySampleLayer];
}
- (void)testSampleAnimationTouch
{
    mySampleLayer.backgroundColor = [UIColor redColor].CGColor;
}

  上述代码中只是创建了一个图层,然后改变了图层的颜色从黑道红,我们能够感觉到颜色的变化并不是瞬间的,而是有一个过度。

  即使你不显式的用[CATransaction begin]开始一次事务,任何在一次run loop循环中属性的改变都会被集中起来,然后做一次0.25秒的动画。

2.动画事务

  通过CATransaction的+begin和+commit分别来入栈或者出栈来控制动画的事务。通过这个事务我们能够控制动画的持续事件等。

    // 动画开始
    [CATransaction begin];
    // 事务其他设定
    [CATransaction ..];

    // 动画效果代码

    // 动画提交
    [CATransaction commit];

  如下代码,我们将改变颜色的动画事件持物2秒

- (void)testSampleAnimationTouch
{
    // 动画开始
    [CATransaction begin];

    // 动画将持续2秒
    [CATransaction setAnimationDuration:2.0];

    // 动画效果代码
    mySampleLayer.backgroundColor = [UIColor redColor].CGColor;

    // 动画提交
    [CATransaction commit];
}

  我们明显感觉到颜色的变换过度持续的更久了。

  我们在使用UIView的时候是使用了block的方式,其实内部也是自动帮助我们使用了图层的事务机制来控制的。

  

3.完成块

  在UIView的动画总我们会设定一个block,当动画完毕的时候去触发,同样的图层的事务中也会存在这样的行为

    // 事务完成块
    CATransaction setCompletionBlock:^{
        <#code#>
    }

   如下代码,在2秒背景颜色后将图层旋转90度

- (void)testSampleAnimationTouch
{
    // 动画开始
    [CATransaction begin];

    // 动画将持续2秒
    [CATransaction setAnimationDuration:2.0];

    // 事务完成块
    [CATransaction setCompletionBlock:^{
        CGAffineTransform transform = mySampleLayer.affineTransform;
        transform = CGAffineTransformRotate(transform, M_PI_2);
        mySampleLayer.affineTransform = transform;
    }];

    // 动画效果代码
    mySampleLayer.backgroundColor = [UIColor redColor].CGColor;

    // 动画提交
    [CATransaction commit];
}

  结果发现,颜色还是按照2秒事件渐变,但是旋转却完成的非常快,这是因为完成块并不在事务中,所以默认时间为0.25秒。

4.图层行为:

  我们把改变属性时CALayer自动应用的动画称作行为

4.1图层行为机制:

  当CALayer的属性被修改时候,它会调用-actionForKey:方法,传递属性的名称。剩下的操作都在CALayer的头文件中有详细的说明,

  实质上是如下几步:

  • 图层首先检测它是否有委托,并且是否实现CALayerDelegate协议指定的-actionForLayer:forKey方法。如果有,直接调用并返回结果。
  • 如果没有委托,或者委托没有实现-actionForLayer:forKey方法,图层接着检查包含属性名称对应行为映射的actions字典。
  • 如果actions字典没有包含对应的属性,那么图层接着在它的style字典接着搜索属性名。
  • 最后,如果在style里面也找不到对应的行为,那么图层将会直接调用定义了每个属性的标准行为的-defaultActionForKey:方法。

  我们常常提到UIView的图层已经被禁止了动画,然后我们又可以通过UIView的block或者事务去做简单的动画效果,两者听上去非常的矛盾。其实秘密就在于:

  UIView的图层的代理即为UIView本身,实现了-actionForLayer:forKey方法,但是在此方法中它判断了图层可动画属性的变动是否是在动画block或者动画事务中

  发生的,如果是则返回action也就可以具有动画表现,如果不是则返回nil,这样就不会产生动画属性。

  证明:如下代码中分别在外部和动画块内部调用了-actionForLayer:forKey方法

#pragma UIView的动画机制
-(void) testUIViewAnimation
{
    UIView *myView = [[UIView alloc]init];
    NSLog(@"outer: %@", [myView actionForLayer:myView.layer forKey:@"backgroundColor"]);

    [UIView animateWithDuration:2.0 animations:^{
        NSLog(@"inner: %@", [myView actionForLayer:myView.layer forKey:@"backgroundColor"]);
    }];
}

结果:对于backgroundColor属性,在外部是得到了nil,这就是我们所说的UIView的图层禁止了隐式动画的原因。而在动画块内部则能够得到动画action,也就是在这里修改可动画属性的话则

可以有动画效果。

-- :::] outer: <null>
-- :::] inner: <CABasicAnimation: 0x7a956150>

上述方法我们可以禁止隐式动画我们也可以通过事务的方法来禁止

[CATransaction setDisableActions:YES];

4.2 控制图层行为:

  • UIView关联的图层禁用了隐式动画,对这种图层做动画的唯一办法就是使用UIView的动画函数(而不是依赖CATransaction),或者继承UIView,并覆盖-actionForLayer:forKey:方法,或者直接创建一个显式动画(具体细节见第八章)。
  • 对于单独存在的图层,我们可以通过实现图层的-actionForLayer:forKey:委托方法,或者提供一个actions字典来控制隐式动画。

如下测试中改变背景颜色,新的色块都是从左侧滑入:

-(void) changeLayerAction
{
    //create sublayer
    mySampleLayer = [CALayer layer];
    mySampleLayer.frame = CGRectMake(50.0f, 50.0f, 100.0f, 100.0f);
    mySampleLayer.backgroundColor = [UIColor blueColor].CGColor;

    //add a custom action
    CATransition *transition = [CATransition animation];
    transition.type = kCATransitionPush;
    transition.subtype = kCATransitionFromLeft;
    mySampleLayer.actions = @{@"backgroundColor": transition};

    //add it to our view
    [self.view.layer addSublayer:mySampleLayer];
}

结果:单独存在的图层由于没有指定代理,那么他将直接去自身的actions字典中寻找搜索是否有指定的属性被修改,和指定属性的行为定义。

  我们看到图层的颜色不再是默认的渐变成黑色,而是黑色块会从左到右挤掉现有颜色。 

5. 呈现与模型

  当我们设定一个可动画参数如图层的position的时候,其实一旦设定完毕后position已经是新的值了,但是在屏幕上我们会看到图层是“缓慢”地移动的新的position位置。

  我们把这个“运动中的”图层称之为呈现图层,正如其名,它正是呈现在屏幕上用户得以观察到的图层。而参数改变前已经动画结束后的图层我们称之为模型图层,他们的关系是:

                               

  每个图层属性的显示值都被存储在一个叫做呈现图层的独立图层当中,他可以通过-presentationLayer方法来访问。这个呈现图层实际上是模型图层的复制,但是它的属性值代表了

  在任何指定时刻当前外观效果。换句话说,你可以通过呈现图层的值来获取当前屏幕上真正显示出来的值,在换句话说即使图层静止不动了,那么这个方法返回的图层即使本身。

  5.1 何时需要用到呈现图层

  • 如果你在实现一个基于定时器的动画,而不仅仅是基于事务的动画,这个时候准确地知道在某一时刻图层显示在什么位置就会对正确摆放图层很有用了。
  • 如果你想让你做动画的图层响应用户输入,你可以使用-hitTest:方法来判断指定图层是否被触摸,这时候对呈现图层而不是模型图层调用-hitTest:会显得更有意义,因为呈现图层代表了用户当前看到的图层位置,而不是当前动画结束之后的位置。

  例子:下面的代码中我们我们创建了一个图层,当在点击图层的时候就随机变换颜色,当积极到其他位置的时候就会缓慢移动到点击位置。

#pragma 呈现图层
- (void) testPresentLayer
{
    //create a red layer
    mySampleLayer = [CALayer layer];
    mySampleLayer.frame = CGRectMake(, , , );
    mySampleLayer.position = CGPointMake(self.view.bounds.size.width / , self.view.bounds.size.height / );
    mySampleLayer.backgroundColor = [UIColor redColor].CGColor;
    [self.view.layer addSublayer:mySampleLayer];
}

-(void)testPresentLayerTouch:(NSSet<UITouch *> *)touches
{
    //get the touch point
    CGPoint point = [[touches anyObject] locationInView:self.view];
    //check if we've tapped the moving layer
    if ([mySampleLayer.presentationLayer hitTest:point]) {
        //randomize the layer background color
        CGFloat red = arc4random() / (CGFloat)INT_MAX;
        CGFloat green = arc4random() / (CGFloat)INT_MAX;
        CGFloat blue = arc4random() / (CGFloat)INT_MAX;
        mySampleLayer.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0].CGColor;

    } else {

        //otherwise (slowly) move the layer to new position
        [CATransaction begin];
        [CATransaction setAnimationDuration:4.0];
        mySampleLayer.position = point;
        [CATransaction commit];
    }
}

  结果:

总结:上述讲述了隐式动画。

动画基础--基于Core Animation(3)的更多相关文章

  1. 动画基础--基于Core Animation(2)

    参考:https://zsisme.gitbooks.io/ios-/content/ 前面的文章动画基础--基于Core Animation(1)提到了图层的基本概念以及可动画参数几何学等知识. 本 ...

  2. 动画基础--基于Core Animation(1)

    1.简介 上一篇文章[New learn]动画-基于UIView了解到了一些直接由UIView这个在UIKIT提供的类中提供的一些动画方法. 使用UIView的动画特性已经能够满足我们很多的需求,它是 ...

  3. iOS 动画效果:Core Animation & Facebook's pop

    本文转载至 http://www.cocoachina.com/ios/20151223/14739.html 感谢原创作者分享 前言相信很多人对实现 iOS 中的动画效果都特别头疼,往往懒得动手,功 ...

  4. iOS 动画篇 之 Core Animation (一)

    iOS中实现动画有两种方式,一种是自己不断的通过drawRect:方法来绘制,另外一种就是使用核心动画(Core Animation). 导语: 核心动画提供高帧速率和流畅的动画,而不会增加CPU的负 ...

  5. Expression Blend实例中文教程(7) - 动画基础快速入门Animation

    通过前面文章学习,已经对Blend的开发界面,以及控件有了初步的认识.本文将讲述Blend的一个核心功能,动画设计.大家也许注意到,从开篇到现在,所有的文章都是属于快速入门,是因为这些文章,都是我曾经 ...

  6. 转 iOS Core Animation 动画 入门学习(一)基础

    iOS Core Animation 动画 入门学习(一)基础 reference:https://developer.apple.com/library/ios/documentation/Coco ...

  7. iOS Core Animation 动画 入门学习(一)基础

    reference:https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreAnimation_guide ...

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

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

  9. Core Animation 动画

    Core Animation框架 Core Animation可以作用与动画视图或者其他可视元素,为你完成了动画所需的大部分绘帧工作.你只需要配置少量的动画参数(如开始点的位置和结束点的位置)即可使用 ...

随机推荐

  1. Unable to open connection to "Microsoft SQL Server, provider V1.0.5000.0 in framework

    解决办法:1 以管理员身份登陆2 找到ORACLE_HOME文件夹(D:\oracle\ora92),点右键,选属性——安全,在组或用户栏中选"Authenticated Users&quo ...

  2. UOJ117:欧拉回路——题解

    http://uoj.ac/problem/117 (作为一道欧拉回路的板子题,他成功的令我学会了欧拉回路) (然而我不会背……) 就两件事: 1.无向图为欧拉图,当且仅当为连通图且所有顶点的度为偶数 ...

  3. 关于PDO取得结果集的数据类型为string的问题

    很久没写些什么了, 正好今天工作中遇到了以前在意过的问题. 之前曾注意到过,php从数据库中取得的结果集后,其中的字段全都会变成string类型.今儿通过ajax调取数据, 有一个type字段是int ...

  4. Codeforces Round #392 (Div. 2) A B C 水 模拟 暴力

    A. Holiday Of Equality time limit per test 1 second memory limit per test 256 megabytes input standa ...

  5. ListBox, ListView, GridView

    ListView是ListBox的派生类,而GridView是ViewBase的派生类 ListView的View属性是ViewBase,所以GridView可以作为ListView的属性 如 < ...

  6. Java设计模式の装饰者模式

    目录 一.问题引入 二.设计原则 三.用装饰者模式解决问题 四.装饰者模式的特点 五.装饰者模式的定义 六.装饰者模式的实现 七.java.io包内的装饰者模式 一.问题引入 咖啡店的类设计: 一个饮 ...

  7. [LeetCode] 数组的最长连续数, O(n)解法

    Longest Consecutive Sequence Given an unsorted array of integers, find the length of the longest con ...

  8. mysql 联合索引匹配原则

    读mysql文档有感 看了mysql关于索引的文档,网上有一些错误的博客文档,这里我自己记一下. 几个重要的概念 1.对于mysql来说,一条sql中,一个表无论其蕴含的索引有多少,但是有且只用一条. ...

  9. 异常的概念和Java异常体系结构

    一. 异常的概念和Java异常体系结构     异常是程序运行过程中出现的错误.本文主要讲授的是Java语言的异常处理.Java语言的异常处理框架,     是Java语言健壮性的一个重要体现. Ja ...

  10. 2015/8/29 Python基础(3):数值

    数字提供了标量储存和直接访问,是不可更改类型,每次变更数值会产生新的对象.Python支持多种数字类型,包括整型.长整型.布尔型.双精度浮点.十进制浮点和复数.在Python中,变量并不是一个盒子,而 ...