动画基础--基于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可以作用与动画视图或者其他可视元素,为你完成了动画所需的大部分绘帧工作.你只需要配置少量的动画参数(如开始点的位置和结束点的位置)即可使用 ...
随机推荐
- 【刷题】BZOJ 1143 [CTSC2008]祭祀river
Description 在遥远的东方,有一个神秘的民族,自称Y族.他们世代居住在水面上,奉龙王为神.每逢重大庆典, Y族都会在水面上举办盛大的祭祀活动.我们可以把Y族居住地水系看成一个由岔口和河道组成 ...
- mybaties分页
首先引入jar包: <dependency> <groupId>com.github.pagehelper</groupId> <artifactId> ...
- [ldap]ldap相关问题
背景: ldap数据库要同步,按照如下操作步骤: 1.导出: 使用slapcat,slapcat直接对数据库操作, slapcat 2.将所需的条目取出,生成文件in.ldif 3.在目标机器上导入: ...
- Leetcode 234. 回文链表(进阶)
1.题目描述 请判断一个链表是否为回文链表. 示例 1: 输入: 1->2 输出: false 示例 2: 输入: 1->2->2->1 输出: true 进阶: 你能否用 O ...
- NYOJ 737DP
石子合并(一) 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的 ...
- java nio buffer读取数据乱码问题
public static void main(String[] args) throws IOException { String charsetName = "GBK"; St ...
- 剑指offer --合并链表
题目:输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. 解法://递归解法 public class MixLink { /* public class L ...
- 图论:Prufer编码-Cayley定理
BZOJ1430:运用Cayley定理解决树的形态统计问题 由Prufer编码可以引申出来一个定理:Cayley 内容是不同的n结点标号的树的数量为n^(n-2) 换一种说法就是一棵无根树,当知道结点 ...
- Packet Tracer 5.0 构建CCNA实验(2)—— 配置VLAN
Packet Tracer 5.0 构建CCNA实验(2)—— 配置VLAN Vlan(Virtual Local Area Network) 即虚拟局域网.VLAN可以把同一个物理网络划分为多个逻辑 ...
- [洛谷P2365] 任务安排
洛谷题目链接:任务安排 题目描述 N个任务排成一个序列在一台机器上等待完成(顺序不得改变),这N个任务被分成若干批,每批包含相邻的若干任务.从时刻0开始,这些任务被分批加工,第i个任务单独完成所需的时 ...