iOS 動畫之CoreAnimation(CALayer)

joker_king發表於2018-12-20

CoreAnimation基本介紹

  • CoreAnimation動畫位於iOS框架的Media
  • CoreAnimation動畫實現需要新增QuartzCore.Framework
  • CoreAnimation基本上是Layer Animation

CoreAnimation分類

  • 隱式動畫:無需指定任何動畫的型別,僅僅改變一個屬性,然後CoreAnimation來決定 如何計時去做動畫。
  • 顯示動畫:對一些屬性做指定的自定義動畫,或建立非線性動畫,比如沿著任意一條曲線移動。

CoreAnimation作用

與UIView動畫相比,CoreAnimation能夠實現更多複雜、好看、高效的動畫效果。

  • 陰影,圓角,帶顏色的邊框。
  • 3D變化。
  • 透明遮罩
  • 多級非線性動畫

CoreAnimation的三種動畫

  • CABasicAnimation基本單一型別的動畫,通過設定起始點,終點,時間,動畫會沿著你這設定點進行移動。可以看做特殊的CAKeyFrameAnimation 。
  • CAKeyframeAnimation幀動畫主要操作屬性有keyPathvalues值組合Keyframe顧名思義就是關鍵點的frame,你可以通過設定CALayer的始點、中間關鍵點、終點的frame,時間,動畫會沿你設定的軌跡進行移動。
  • CAAnimationGroup組合動畫 操作屬性animationsCAAnimation型別的動畫加入陣列,以FIFO佇列的方式執行。
  • CATransition這個就是蘋果幫開發者封裝好的一些動畫

CABasicAnimation

三個重要的屬性

@property(nullable, strong) id fromValue;動畫的效果變化的初始值
@property(nullable, strong) id toValue;動畫效果變化的結束值(絕對值)
@property(nullable, strong) id byValue;動畫效果變化的結束值(相對值)
複製程式碼

這三個屬性必須要有一個有值,它們的值就是原來檢視的放大,旋轉等倍數或者角度。

  • fromValuetoValue不為空,動畫的效果會從fromValue的值變化到toValue
  • fromValuebyValue都不為空,動畫的效果將會從fromValue變化到fromValue+byValue
  • toValuebyValue都不為空,動畫的效果將會從toValue-byValue變化到toValue
  • 只有fromValue的值不為空,動畫的效果將會從fromValue的值變化到當前的狀態。
  • 只有toValue的值不為空,動畫的效果將會從當前狀態的值變化到toValue的值。
  • 只有byValue的值不為空,動畫的效果將會從當前的值變化到(當前狀態的值+byValue)的值。

想要實現不同的效果,最關鍵的地方在於CABasicAnimation物件的初始化方式中keyPath的設定。在iOS中有以下幾種不同的keyPath,代表著不同的效果:

transform.rotation.x //以x軸為中心旋轉
transform.rotation.y //以y軸為中心旋轉
transform.rotation.z //以z軸為中心旋轉
transform.scale.x //縮放x軸方向
transform.scale.y //縮放y軸方向
transform.scale.z //縮放z軸方向,這個一般不會用到。
transform.scale //x,y方向整體縮放,z方向沒看到效果。
複製程式碼

下面我們來簡單的做一個動畫

- (void)springAnimation{
    CABasicAnimation *base = [CABasicAnimation animationWithKeyPath:@"transform.scale.y"];
/*在動畫結束之後是否讓動畫回到原處,這個屬性的預設值是YES(回到原處),此時*fillMode*是沒有作用的
如果設定為NO那麼就需要設定一個*fillMode*屬性,就是動畫結束之後的狀態,如果不設定,動畫也會回到原處。*/
    base.removedOnCompletion = NO;
//動畫結束之後狀態的設定
    base.fillMode = kCAFillModeForwards;
    base.fromValue = @(2);
//動畫時長
        base.duration = 10;
//動畫的重複次數
        base.repeatCount = 100;
//給base動畫設定延時啟動
    base.beginTime = 2 + CACurrentMediaTime();
//動畫是否按原路徑返回
    base.autoreverses = YES;
//將動畫新增到layer層*forKey*是給動畫新增一個標記,方便刪除。
        [self.redView.layer addAnimation:base forKey:@"basic"];
}
複製程式碼

刪除動畫的方法

-(void)removeAnimationForKey:(NSString *)key;
key:你需要刪除的動畫的名稱。
這個方法就是你把動畫新增到那個檢視的layer層上,就由那個檢視的layer來呼叫。
-(void)removeAllAnimations;
這個法是刪除這個檢視layer層上的所有動畫。
複製程式碼

在這裡簡單介紹一下fillMode 注意fillMode這個屬性,必須要配合下面這個屬性來使用。這個屬性的預設值是YES(回到原處),此時fillMode是沒有作用的如果設定為NO那麼就需要設定一個fillMode屬性,就是動畫結束之後的狀態,如果不設定,動畫也會回到原處。

base.removedOnCompletion = NO;
複製程式碼
kCAFillModeRemoved 這個是預設值,也就是說當動畫開始前和動畫結束後,動畫對layer都沒有影響,動畫結束後,layer會恢復到之前的狀態 
kCAFillModeForwards 當動畫結束後,layer會一直保持著動畫最後的狀態 
kCAFillModeBackwards 這個和kCAFillModeForwards是相對的,就是在動畫開始前,你只要將動畫加入了
一個layer,layer便立即進入動畫的初始狀態並等待動畫開始.你可以這樣設定測試程式碼,將一個動畫加入一個
layer的時候延遲5秒執行.然後就會發現在動畫沒有開始的時候,只要動畫被加入了layer,layer便處於動畫初
始狀態 
kCAFillModeBoth 理解了上面兩個,這個就很好理解了,這個其實就是上面兩個的合成.動畫加入後開始之
前,layer便處於動畫初始狀態,動畫結束後layer保持動畫最後的狀態.
複製程式碼

CAKeyframeAnimation

這個動畫可以讓你在動畫的一些關鍵的位置來改變動畫的frame以此來達到我們想要的效果。 position是描述動畫檢視的位置資訊的,簡單理解就是和檢視的中心點一樣,所以我們通過改變position屬性,就可以改變動畫的位置。 與position相對應得是錨點也就是anchorPointanchorPointpositionframe這三者之間有著如下的關係。

position.x = frame.origin.x + anchorPoint.x * bounds.size.width; 
position.y = frame.origin.y + anchorPoint.y * bounds.size.height;
複製程式碼

示例程式碼:下面是讓一個檢視左右震動的動畫

 CAKeyframeAnimation *keyFram = [CAKeyframeAnimation animationWithKeyPath:@"position"];
//layer最初的position值
    float position_x = self.redView.layer.position.x;
    float position_y = self.redView.layer.position.y;
//layer向左晃動的偏移量
    NSValue *leftValue = [NSValue valueWithCGPoint:CGPointMake(position_x - 30, position_y)];
//layer的原始位置
    NSValue *originValue = [NSValue valueWithCGPoint:CGPointMake(position_x, position_y)];
//layer向右晃動的偏移量
    NSValue *right = [NSValue valueWithCGPoint:CGPointMake(position_x + 30, position_y)];
//新增每一幀的Value值
    [keyFram setValues:@[originValue,leftValue,originValue,right,originValue]];
    keyFram.repeatCount = 10;
    keyFram.repeatDuration = 1;
//為layer層新增動畫
     [self.redView.layer addAnimation:keyFram forKey:@"aaa"];
複製程式碼

CAAnimationGroup

CAAnimationGroup是一個組合動畫,所謂的組合動畫就是將多個動畫組合到一起讓它產生很炫酷的效果。 注意:所有的組合動畫,它的延遲啟動,重複次數等屬性,同一在組裡面設定,不要在單一的動畫裡面設定,以免出現問題。

  • 第一步:初始化組合動畫
CAAnimationGroup *group = [CAAnimationGroup animation];
複製程式碼
  • 第二步建立至少兩個動畫
    CABasicAnimation *base = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    /*在動畫結束之後是否讓動畫回到原處,這個屬性的預設值是YES(回到原處),此時*fillMode*是沒有作用的
     如果設定為NO那麼就需要設定一個*fillMode*屬性,就是動畫結束之後的狀態,如果不設定,動畫也會回到原處。*/
    base.removedOnCompletion = NO;
    //動畫結束之後狀態的設定
    base.fillMode = kCAFillModeForwards;
    base.fromValue = @(M_PI);
    //動畫是否按原路徑返回
    base.autoreverses = YES;
/************************************************************************************************/
    CAKeyframeAnimation *keyFram = [CAKeyframeAnimationanimationWithKeyPath:@"position"];
    //layer最初的position值
    float position_x = self.redView.layer.position.x;
    float position_y = self.redView.layer.position.y;
    //layer向左晃動的偏移量
    NSValue *leftValue = [NSValue valueWithCGPoint:CGPointMake(position_x - 50, position_y)];
    //layer的原始位置

    NSValue *originValue = [NSValue valueWithCGPoint:CGPointMake(position_x, position_y)];
    //layer向右晃動的偏移量
    NSValue *right = [NSValue valueWithCGPoint:CGPointMake(position_x + 50, position_y)];
    //新增每一幀的Value值
    [keyFram setValues:@[originValue,leftValue,originValue,right,originValue]];
複製程式碼
  • 第三步將得到的動畫放入group中
group.animations = @[base,keyFram];
    //將group加到layer上
    group.repeatCount = 100;
    group.repeatDuration = 10;
    [self.redView.layer addAnimation:group forKey:@"group"];
複製程式碼

以上就是有關於CoreAnimation的簡單介紹了,謝謝觀看。

相關文章