《A GUIDE TO IOS ANIMATION 2.0》(杨骑滔)三章.CoreAnimation-学习笔记: 源码分析和盲点记录

21- 《A GUIDE TO IOS ANIMATION 2.0》(杨骑滔)三章.CoreAnimation-学习笔记: 源码分析和盲点记录

第一个案例: Twitter 的启动动画

这个案例之前有看过.当时觉得很有意思. 今天看了杨骑滔给出的实现思路之后,才发现实现代码不难,难的还是你的实现的思路. 我们仔细观察,书中的启动动画,开始的页面是从程序启动之后一直到进入根控制器都是同一个,而且明显,要比我们平时的启动界面停留的时间要长.这个的实现思路和我们看到的很多主流APP进入之后,会有一个广告界面,还有倒计时.这个肯定是系统自带的LaunchScreen.xib启动完成之后,在显示根控制器之前穿插的. 只不过,广告和启动是不同的页面,我们这里是需要两个样式一模一样的页面.

原理,我就不赘述了.我想看了书的人和看了源码的人早已经了然于胸. 现在只是记录下自己的知识的盲点.

UIWindow的两个方法

[self.window makeKeyAndVisible];self.window.rootViewController的具体作用:

-------- 占位行 ------------

mask属性

“在开始之前,我们先了解一下 Layer 的 mask 属性。
@property(strong) CALayer *mask;
可以发现 mask 也是一个 CALayer”
--- 摘录来自: 杨骑滔(KittenYang). “A GUIDE TO IOS ANIMATION”。 iBooks.

 //logo mask 添加一个遮罩,图片透明和不透明的地方反转
CALayer *maskLayer = [CALayer layer];
maskLayer.contents = (id)[UIImage imageNamed:@"1"].CGImage; //必须是CGImageRef
maskLayer.position = navc.view.center;
maskLayer.bounds = CGRectMake(0, 0, 60, 60);
navc.view.layer.mask = maskLayer; //为mask(CALayer)属性赋值之后,露出window是黑色的,必须通过改变self.window.background的颜色

CoreAnimation - CAKeyframeAnimation

---- 以下均为原文,摘录来自: 杨骑滔(KittenYang). “A GUIDE TO IOS ANIMATION”。 iBooks.

  1. 顾名思义,CAKeyframeAnimation 就相当于 Flash 里的关键帧动画”
  1. CAKeyframeAnimation 中我们通过 keyPath 就可以指定动画的类型。”
  2. 然后,我们把每个关键帧的对应参数赋值给 CAKeyframeAnimation 的 values 属性。代码中,我设置了3个关键帧,transformAnimation.values = xxx
  3. 设置对应的时间点 transformAnimation.keyTimes = xxx
  4. 但是我们还要注意。当你给一个 CALayer 添加动画的时候,动画其实并没有改变这个 layer 的实际属性。取而代之的,系统会创建一个原始 layer 的拷贝。在文档中,苹果称这个原始 layer 为 Model Layer ,而这个复制的 layer 则被称为 Presentation Layer 。 Presentation Layer 的属性会随着动画的进度实时改变,而 Model Layer 中对应的属性则并不会改变。所以如果你想要获取动画中每个时刻的状态,请使用 layer 的 func presentationLayer() -> AnyObject!
  5. 为了让动画在结束之后不突然回到了初始状态, 引出 removedOnCompletion 和 fillMode 了。
    removedOnCompletion 的官方解释是:
    /* When true, the animation is removed from the render tree once its
    • active duration has passed. Defaults to YES. */

也就是默认情况下系统会在 duration 时间后自动移除这个 CAKeyframeAnimation。当 remove 了某个动画,那么系统就会自动销毁这个 layer 的 Presentation Layer ,只留下 Model Layer ”

  1. 你需要先把 removedOnCompletion 设置为 false ,然后设置 fillMode 为kCAFillModeForwards” (TIPS: 对于 CAAnimation ,你需要将其 removedOnCompletion 设置为 false 才行,要不然 fillMode 将不起作用。”)。但设置 removedOnCompletion 和 fillMode 不是正确的方式(这个之后再详细说明)。
  2. 所以一个好动画离不开一堆好参数。

第二个案例: 圆圈遮罩的转场动画

这个案例讲的是转场动画,这个Demo的效果可以看格瓦拉选中一个条目之后,

关于转场动画

“iOS7 开始苹果推出了自定义转场的 API 。从此,任何可以用 CoreAnimation 实现的动画,都可以出现在两个 ViewController 的切换之间。”

“苹果在 UINavigationControllerDelegateUIViewControllerTransitioningDelegate 中给出了几个协议方法,通过返回类型就可以很清楚地知道各自的具体作用。你只需要重载它们,然后 return 一个动画的实例对象,一切都搞定了。使用准则就是:UINavigationController pushViewController 时重载 UINavigationControllerDelegate 的方法;UIViewController presentViewController 时重载 UIViewControllerTransitioningDelegate 的方法。”

——摘录来自: 杨骑滔(KittenYang). “A GUIDE TO IOS ANIMATION”。 iBooks.

实现步骤

1.根据第一小节中提到的关于转场动画的解释,是说我们在当天起始跳转控制器中实现对应的 push 或者 present对应的代理方法.
2.创建继承自 NSObject 并且声明 UIViewControllerAnimatedTransitioning 的的动画类
3.重载 UIViewControllerAnimatedTransitioning 中的协议方法。

就这三步. 具体的转场效果,在第3步中自行定义,你写成啥样的,他就按照给你样转

案例分析

再回到我们这个案例.这个效果,其实是两个有形状的UIBezierPath的贝塞尔曲线对象的path值,分别作为CABasicAnimation对象的起始值到终点值. 然后系统内部发生的变化. 参看下边代码:

maskLayerAnimation.fromValue = (__bridge id)(maskStartBP.CGPath);
maskLayerAnimation.toValue = (__bridge id)((maskFinalBP.CGPath));

杨骑滔在animateTransition:方法中,首先获取到跳转和跳转到的控制器,然后把这两个控制器的view添加到transitionContext.containerView中,接着创建两个圆形的UIBezierPath对象,最终的转成效果类似我们案例一.实现代码也有类似的地方.

其中,第一个需要注意的地方是:触发点的判断,判断在哪个象限,然后得出出发点的坐标,如果你对象限有点遗忘的话,你可以看下边这幅图,马上就想起来了:


http://blog.csdn.net/ys410900345/article/details/42924827

/** timingFunction 
 * 
 *  用于变化起点和终点之间的插值计算,形象点说它决定了动画运行的节奏,比如是均匀变化(相同时间变化量相同)还是 
 *  先快后慢,先慢后快还是先慢再快再慢. 
 * 
 *  动画的开始与结束的快慢,有五个预置分别为(下同): 
 *  kCAMediaTimingFunctionLinear            线性,即匀速 
 *  kCAMediaTimingFunctionEaseIn            先慢后快 
 *  kCAMediaTimingFunctionEaseOut           先快后慢 
 *  kCAMediaTimingFunctionEaseInEaseOut     先慢后快再慢 
 *  kCAMediaTimingFunctionDefault           实际效果是动画中间比较快. 
 */  

《IOS 30多个iOS常用动画,带详细注释》

推荐阅读更多精彩内容