动画基础--基于Core Animation(3)
参考: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)的更多相关文章
- 动画基础--基于Core Animation(2)
参考:https://zsisme.gitbooks.io/ios-/content/ 前面的文章动画基础--基于Core Animation(1)提到了图层的基本概念以及可动画参数几何学等知识. 本 ...
- 动画基础--基于Core Animation(1)
1.简介 上一篇文章[New learn]动画-基于UIView了解到了一些直接由UIView这个在UIKIT提供的类中提供的一些动画方法. 使用UIView的动画特性已经能够满足我们很多的需求,它是 ...
- iOS 动画效果:Core Animation & Facebook's pop
本文转载至 http://www.cocoachina.com/ios/20151223/14739.html 感谢原创作者分享 前言相信很多人对实现 iOS 中的动画效果都特别头疼,往往懒得动手,功 ...
- iOS 动画篇 之 Core Animation (一)
iOS中实现动画有两种方式,一种是自己不断的通过drawRect:方法来绘制,另外一种就是使用核心动画(Core Animation). 导语: 核心动画提供高帧速率和流畅的动画,而不会增加CPU的负 ...
- Expression Blend实例中文教程(7) - 动画基础快速入门Animation
通过前面文章学习,已经对Blend的开发界面,以及控件有了初步的认识.本文将讲述Blend的一个核心功能,动画设计.大家也许注意到,从开篇到现在,所有的文章都是属于快速入门,是因为这些文章,都是我曾经 ...
- 转 iOS Core Animation 动画 入门学习(一)基础
iOS Core Animation 动画 入门学习(一)基础 reference:https://developer.apple.com/library/ios/documentation/Coco ...
- iOS Core Animation 动画 入门学习(一)基础
reference:https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreAnimation_guide ...
- IOS动画(Core Animation)总结 (参考多方文章)
一.简介 iOS 动画主要是指Core Animation框架.官方使用文档地址为:Core Animation Guide. Core Animation是IOS和OS X平台上负责图形渲染与动画的 ...
- Core Animation 动画
Core Animation框架 Core Animation可以作用与动画视图或者其他可视元素,为你完成了动画所需的大部分绘帧工作.你只需要配置少量的动画参数(如开始点的位置和结束点的位置)即可使用 ...
随机推荐
- [洛谷P3261][JLOI2015]城池攻占
题目大意:有$n$个点的树,第$i$个节点有一个权值$h_i$,$m$个骑士,第$i$个骑士攻击力为$v_i$,一个骑士可以把从它开始的连续的父亲中比它小的节点攻破,攻破一个节点可以把攻击力加或乘一个 ...
- LOJ2351:[JOI2017/2018决赛]毒蛇越狱——题解
https://loj.ac/problem/2351 参考:https://www.cnblogs.com/ivorysi/p/9144676.html 但是参考博客讲解太吓人了,我们换一种通俗易懂 ...
- 20181022 考试记录&高级数据结构
题目 W神爷的题解 高级数据结构 T1: 其实是一道easy题,$O(n^3log n)$ 也是能卡过去的,本着要的70分的心态,最后尽然A了. 如果是正解则是$O(n^3)$,当确定你要选择的列时, ...
- Nginx反向代理两个tomcat服务器
第一步,在Linux上安装两个tomcat,修改好端口号后,启动起来. 第二步,配置本地的DNS解析,即修改host文件: 第三步,配置Nginx配置文件 反向代理的配置虚拟主机配置差不多也要配置虚拟 ...
- redis中如何对 key 进行分类
因为redis中的 hash是不支持设置过期时间的,如果我们要 设置过期时间,还要分类存储,可以用下面折中的方法 其实就是我们把 key 定义的有规律一些,通过在key的字符串内部 分类,上图只是因为 ...
- hdu 1754 线段树 单点更新 动态区间最大值
I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- 获取Web.Config中节点的值
读取webconfig里面的appSetting和connectionString <appSettings> <add key="SiteURL" value= ...
- mysql 中 group_concat()用法
基本语法:group_concat([DISTINCT] 要连接的字段 [Order BY 排序字段 ASC/DESC] [Separator '分隔符']) 初始数据: ...
- UVA 1649 Binomial coefficients
https://vjudge.net/problem/UVA-1649 题意: 输入m,求所有的C(n,k)=m m<=1e15 如果枚举n,那么C(n,k)先递增后递减 如果枚举k,那么C(n ...
- windows下用时间戳创建文件名
英文环境下: echo Archive_%date:~-4,4%%date:~-10,2%%date:~-7,2%_%time:~0,2%%time:~3,2%%time:~6,2%.zip 中文: ...