动画基础--基于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可以作用与动画视图或者其他可视元素,为你完成了动画所需的大部分绘帧工作.你只需要配置少量的动画参数(如开始点的位置和结束点的位置)即可使用 ...
随机推荐
- vscode Variables Reference
vscode Variables Reference 您可以在以下链接中找到该列表:https://code.visualstudio.com/docs/editor/variables-refere ...
- [JXOI2017]颜色 线段树扫描线 + 单调栈
---题面--- 题解: 首先题目要求删除一些颜色,换个说法就是要求保留一些颜色,那么观察到,如果我们设ll[i]和rr[i]分别表示颜色i出现的最左边的那个点和最右边的那个点,那么题目就是在要求我们 ...
- 【国家集训队】聪聪可可 ——树形DP
感觉是一道很妙的树形DP题,充分利用到了树的性质(虽然说点分治也可以做,,,,但是本蒟蒻不会啊) 然而某Twilight_Sx大佬表示这道题真的非常水,,,本蒟蒻也只能瑟瑟发抖了 本蒟蒻表示还是要经过 ...
- BZOJ3864 & HDU4899:Hero meet devil——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=3864 http://acm.hdu.edu.cn/showproblem.php?pid=4899 ...
- 模板:数论 & 数论函数 & 莫比乌斯反演
作为神秘奖励--?也是为了方便背. 所有的除法都是向下取整. 数论函数: \((f*g)(n)=\sum_{d|n}f(d)g(\frac{n}{d})\) \((Id*\mu)(n)=\sum_{d ...
- POJ.1797 Heavy Transportation (Dijkstra变形)
POJ.1797 Heavy Transportation (Dijkstra变形) 题意分析 给出n个点,m条边的城市网络,其中 x y d 代表由x到y(或由y到x)的公路所能承受的最大重量为d, ...
- B树,B+树,B*树简介
B树(有些人也叫B-树) 是一种多路搜索树 : 1.定义任意非叶子结点最多只有M个儿子:且M>2: 2.根结点的儿子数为[2, M]: 3.除根结点以外的非叶子结点的儿子数为[M/2, M]: ...
- 【简单算法】22.删除链表的倒数第N个节点
题目: 给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点. 示例: 给定一个链表: ->->->->, 和 n = . 当删除了倒数第二个节点后,链表变为 -& ...
- C++分离字符串中的数字和字符 转
#include <iostream> #include <string> #include <vector> using namespace std; void ...
- PhoneGap API介绍:Camera
本文将介绍PhoneGap API——Camera:使用设备的摄像头采集照片,对象提供对设备默认摄像头应用程序的访问. 方法: camera.getPicture 参数: cameraSuccess ...