动画基础--基于Core Animation(3)

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

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

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

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

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

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

首先需要总结的是:

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

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

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

  

1.隐式动画

 简单的隐式动画:

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

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

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

    mySampleLayer = [CALayer layer];
    mySampleLayer.backgroundColor = [UIColor blackColor].CGColor;
    mySampleLayer.frame = CGRectMake(50, 50, 150, 150);
    [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,也就是在这里修改可动画属性的话则

可以有动画效果。

2016-05-12 16:33:40.970 TestCoreAnim[1067:41601] outer: <null>
2016-05-12 16:33:40.972 TestCoreAnim[1067:41601] 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(0, 0, 100, 100);
    mySampleLayer.position = CGPointMake(self.view.bounds.size.width / 2, self.view.bounds.size.height / 2);
    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];
    }
}

  结果:

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

时间: 2024-10-10 02:50:25

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

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

参考:https://zsisme.gitbooks.io/ios-/content/ 前面的文章动画基础--基于Core Animation(1)提到了图层的基本概念以及可动画参数几何学等知识. 本片文章将继续探讨更加深入的动画知识. 6.视觉效果 圆角 圆角设定可以让原本死板的直角视图更加美观和谐:> -(void)radiusView { radiusView = [[UIView alloc]initWithFrame:CGRectMake(100.0f, 50.0f, 100.0f,

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

1.简介 上一篇文章[New learn]动画-基于UIView了解到了一些直接由UIView这个在UIKIT提供的类中提供的一些动画方法. 使用UIView的动画特性已经能够满足我们很多的需求,它是对于Core Animation的底层方法做了了高级抽象,使得我们开发动画更加便捷,但是便捷的另外一边就失去了Core Animation框架的 完整性和灵活性.当然除了这些UIView还提供了很多用户交互上的功能如相应用户点击等. 那么我们什么时候回正真要去操作更加底层的Core Animatio

核心动画编程指南Core Animation Programming Guide - iOS

1 有关核心动画 1.1 概览 1.1.1 Core Animation 管理应用的内容 核心是 layer objects, 1.1.2 更改 layer 触发动画 Like views, layer objects have a bounds rectangle, a position onscreen, an opacity, a transform, and many other visually-oriented properties that can be modified. 更改这

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

通过前面文章学习,已经对Blend的开发界面,以及控件有了初步的认识.本文将讲述Blend的一个核心功能,动画设计.大家也许注意到,从开篇到现在,所有的文章都是属于快速入门,是因为这些文章,都是我曾经学习的经验和工作中使用到的经验总结出来的.在我个人认为,掌握了这些核心功能也就等于掌握了Blend的开发方法.在以后开发项目中使用Blend开发工具,这些知识应该足够用了.当然,特殊项目也需要特殊对待,如果您在项目开发中,有新的Blend开发经验,希望您能够毫不吝啬的分享,在这里,我表示深深的谢意.

iOS开发-核心动画高级编程Core Animation系列(转)

iOS-Core-Animation-Advanced-Techniques 转 GitHub译文 iOS核心动画高级编程全集 iOS-核心动画高级编程/1-图层树 iOS-核心动画高级编程/2-寄宿图 iOS-核心动画高级编程/3-图层几何学 iOS-核心动画高级编程/4-视觉效果 iOS-核心动画高级编程/5-变换 iOS-核心动画高级编程/6-专有图层 iOS-核心动画高级编程/7-隐式动画 iOS-核心动画高级编程/8-显示动画 iOS-核心动画高级编程/9-图层时间 iOS-核心动画高

iOS Core Animation Advanced Techniques(六): 基于定时器的动画和性能调优

基于定时器的动画 我可以指导你,但是你必须按照我说的做. -- 骇客帝国 在第10章“缓冲”中,我们研究了CAMediaTimingFunction,它是一个通过控制动画缓冲来模拟物理效果例如加速或者减速来增强现实感的东西,那么如果想更加真实地模拟 物理交互或者实时根据用户输入修改动画改怎么办呢?在这一章中,我们将继续探索一种能够允许我们精确地控制一帧一帧展示的基于定时器的动画. 定时帧 动画看起来是用来显示一段连续的运动过程,但实际上当在固定位置上展示像素的时候并不能做到这一点.一般来说这种显

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

iOS Core Animation 动画 入门学习(一)基础 reference:https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreAnimation_guide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40004514 在iOS中,每个view中都自动配置了一个layer,我们不能人为新建,而在Mac OS中,view默认是没有

iOS Core Animation Advanced Techniques(四):隐式动画和显式动画

隐式动画 按照我的意思去做,而不是我说的. -- 埃德娜,辛普森 我们在第一部分讨论了Core Animation除了动画之外可以做到的任何事情.但是动画师Core Animation库一个非常显著的特性.这一章我们来看看它是怎么做到的.具体来说,我们先来讨论框架自动完成的隐式动画(除非你明确禁用了这个功能). 事务 Core Animation基于一个假设,说屏幕上的任何东西都可以(或者可能)做动画.动画并不需要你在Core Animation中手动打开,相反需要明确地关闭,否则他会一直存在.

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

一.简介 iOS 动画主要是指Core Animation框架.官方使用文档地址为:Core Animation Guide. Core Animation是IOS和OS X平台上负责图形渲染与动画的基础框架.Core Animation可以作用与动画视图或者其他可视元素,为你完成了动画所需的大部分绘帧工作.你只需要配置少量的动画参数(如开始点的位置和结束点的位置)即可使用Core Animation的动画效果.Core Animation将大部分实际的绘图任务交给了图形硬件来处理,图形硬件会加