CoreAnimation詳解(一)有關Layer的動畫,coreanimationlayer
原創Blog,轉載請註明出處
我的IOS SDK詳解專欄,地址
http://blog.csdn.net/column/details/huangwenchen-ios-sdk.html
本文主要從CoreAnimation的Layer角度來講解動畫,我想從CALayer的角度更好理解,後續還會有第二篇從UIKIt的UIView角度來講解動畫,第三篇講解UIDynamicAnimation,第三篇我會講到UIViewController切換時候的動畫。
本文主要涵蓋四個部分
1.基礎動畫-會講到時間函數和一些關鍵的屬性
2.基於主要畫面格的動畫-講到沿著指定路徑啟動並執行動畫
3.動畫組-多個動畫組合到一起形成複雜的動畫
4.簡單講一下講一下有關動畫的代理
(一)為什麼要設計動畫?
動畫提供了一個漸層的方式來表達變化,使用動畫可以避免各種介面突變,造成使用者困惑。
IOS中,使用CoreAnimation只要指定始末狀態或者主要畫面格的狀態,CoreAnimation會高效的為我們建立補間動畫。
(二)從CALayer的角度來看的三種動畫
首先不熟悉CALayer的同學看看前兩篇的CALayer的內容,這是CoreAnimation的基礎。這裡我重複的介紹兩種CALayer的Tree。
Presentation Tree-對應在動畫的過程中,CALayer的屬性
Model Tree-對應CALayer的實際屬性。
通過使用 -[CALayer presentationLayer] 和 -[CALayer modelLayer]可以訪問兩種Tree
動畫的過程實際上是修改Presentation Tree
2.1 基礎的動畫
第一個簡單的動畫,我希望imageview向右移動100的距離,移動方式easeInOut(加速開始,減速結束)。
效果
代碼如下,通常有兩種方式來影響動畫
<pre name="code" class="objc"> CABasicAnimation * animation = [CABasicAnimation animation]; animation.keyPath = @"position.x";//KVC的方式來訪問屬性 animation.fromValue = @(self.imageview.layer.position.x);//該屬性開始的值 animation.toValue = @(self.imageview.layer.position.x + 100);//結束的值 animation.duration = 1;//期間 animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];//結束函數 [self.imageview.layer addAnimation:animation forKey:@"basic"];//添加動畫
通過fromValue和toValue是一種方式,當然也可以通過byValue的方式,byValue在初值上加上byValue的變化,通過以下代碼也可以實現上述動畫
CABasicAnimation * animation = [CABasicAnimation animation]; animation.keyPath = @"position.x"; animation.byValue = @(100); animation.duration = 1; animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; [self.imageview.layer addAnimation:animation forKey:@"basic"];
但是,結束後會發現,imageview又恢複到原處。這是因為在動畫的過程中,我們修改的是Presentation Tree,並沒有實際修改CALayer的屬性。想要讓動畫停在結束的位置,通常有兩種方式,
(1)修改屬性
代碼如下
CABasicAnimation * animation = [CABasicAnimation animation]; animation.keyPath = @"position.x"; animation.fromValue = @(self.imageview.layer.position.x); animation.toValue = @(self.imageview.layer.position.x + 100); animation.duration = 1; animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; [self.imageview.layer addAnimation:animation forKey:@"basic"]; self.imageview.layer.position = CGPointMake(self.imageview.layer.position.x+100, self.imageview.layer.position.y);
(2)設定讓動畫停在結束的位置
<pre name="code" class="objc"> CABasicAnimation * animation = [CABasicAnimation animation]; animation.keyPath = @"position.x"; animation.fromValue = @(self.imageview.layer.position.x); animation.toValue = @(self.imageview.layer.position.x + 100); animation.duration = 1; animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; animation.removedOnCompletion = NO;//動畫結束了禁止刪除 animation.fillMode = kCAFillModeForwards;//停在動畫結束處 [self.imageview.layer addAnimation:animation forKey:@"basic"];
一般採用前者,因為動畫往往的結束是實際的屬性的改變。
這裡再講解下時間函數
時間函數決定了動畫如何執行,時間函數決定了動畫的數學模型,比如速度速度最好不要有突變, 系統提供的時間函數有以下幾種
NSString *constkCAMediaTimingFunctionLinear;線性
NSString *constkCAMediaTimingFunctionEaseIn;加速進入
NSString *constkCAMediaTimingFunctionEaseOut;減速停止
NSString*constkCAMediaTimingFunctionEaseInEaseOut;加速進入減速停止,這個是常用的
NSString *constkCAMediaTimingFunctionDefault;預設
當然,時間函數支援自訂,用如下函數
functionWithControlPoints::::
這個函數的4個點決定了一個三維的貝茲路徑來決定時間函數。這裡不深入講解了。
最後,這一點尤為重要,就是在傳遞CAAnimation的對象或者子類給Layer的時候,傳遞的是copy
2.2 基於主要畫面格的動畫
以下是一個基於主要畫面格建立的抖動的動畫,採用在時間點對應的位置來建立動畫
CAKeyframeAnimation * animation = [CAKeyframeAnimation animation]; animation.keyPath = @"position.x"; NSInteger initalPositionX = self.imageview.layer.position.x; animation.values = @[@(initalPositionX), @(initalPositionX + 10), @(initalPositionX - 10), @(initalPositionX + 10), @(initalPositionX)]; animation.keyTimes = @[ @(0), @(1/6.0), @(3/6.0), @(5/6.0), @(1)]; [self.imageview.layer addAnimation:animation forKey:@"keyFrame"];
當然,基於主要畫面格的動畫支援沿著路徑運動,可以設定時間函數來決定運動的方式
例如以下建立一個比較複雜的運動,首先移動到(200,200),然後沿著以該點為圓心,逆時針旋轉半圈,最後停在結束的位置。
動畫的過程中,imageview沿著路徑轉動
CAKeyframeAnimation * animation = [CAKeyframeAnimation animation]; animation.keyPath = @"position"; //Create Path CGMutablePathRef mutablepath = CGPathCreateMutable(); CGPathMoveToPoint(mutablepath, nil,self.imageview.layer.position.x, self.imageview.layer.position.y); CGPathAddLineToPoint(mutablepath,nil,200,200); CGPathAddArc(mutablepath, nil,200,200,100,0,M_PI,YES); //set path animation.path = mutablepath; animation.duration = 4.0; animation.rotationMode = kCAAnimationRotateAuto; animation.removedOnCompletion = NO;//動畫結束了禁止刪除 animation.fillMode = kCAFillModeForwards;//停在動畫結束處 [self.imageview.layer addAnimation:animation forKey:@"PathAnimation"];
這個動畫的幾幅關鍵
2.3 動畫組
所謂,動畫組就是把幾個動畫組合到一起,然後一起執行,通常複雜的動畫都是由動畫組來實現的。
舉個例子:沿著上個例子的路徑運動,運動的同時透明度漸層。
CAKeyframeAnimation * pathAnimation = [CAKeyframeAnimation animation]; pathAnimation.keyPath = @"position"; //Create Path CGMutablePathRef mutablepath = CGPathCreateMutable(); CGPathMoveToPoint(mutablepath, nil,self.imageview.layer.position.x, self.imageview.layer.position.y); CGPathAddLineToPoint(mutablepath,nil,200,200); CGPathAddArc(mutablepath, nil,200,200,100,0,M_PI,YES); //set path pathAnimation.path = mutablepath; pathAnimation.rotationMode = kCAAnimationRotateAuto; [self.imageview.layer addAnimation:pathAnimation forKey:@"PathAnimation"]; //透明度變化 CAKeyframeAnimation * opacityAnimation = [CAKeyframeAnimation animation]; opacityAnimation.keyPath = @"opacity"; opacityAnimation.values = @[@(1.0), @(0.5), @(0.0), @(0.5), @(1.0)]; opacityAnimation.calculationMode = kCAAnimationPaced; [self.imageview.layer addAnimation:opacityAnimation forKey:@"OpacityAnination"]; //配置動畫組 CAAnimationGroup * animationGroup = [[CAAnimationGroup alloc] init]; animationGroup.animations = @[pathAnimation,opacityAnimation]; animationGroup.duration = 4.0; animationGroup.removedOnCompletion = NO; animationGroup.fillMode = kCAFillModeBackwards; [self.imageview.layer addAnimation:animationGroup forKey:@"GroupAnimation"];
效果的幾幅
(三)動畫的代理
通過設定代理可以監聽動畫開始和結束的事件
通過設定delegate,來監聽兩個函數
animationDidStart:(CAAnimation *)anim
animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
這裡的flag判斷動畫是否執行完畢
最後,附上wiki上設計動畫的12個基本原則
https://en.wikipedia.org/wiki/12_basic_principles_of_animation
BTY:有沒有同學知道CSDN怎麼插入gif圖片?