1. 程式人生 > >iOS layer層關鍵幀動畫

iOS layer層關鍵幀動畫

上次介紹了 UIview的block動畫 ,
這次說一下 view的layer層的關鍵幀動畫
layer層的動畫相對於 view層的動畫 會更輕量。
直接看程式碼 每一個屬性的詳細說明 見程式碼下面的表格

     //先建立一個view用於執行動畫
    UIView * myview = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
    myview.layer.contents = (id)[UIImage imageNamed:@"123"].CGImage;
    myview.center = CGPointMake(CGRectGetWidth(self.view
.frame)/2, CGRectGetHeight(self.view.frame)/2); /* //可以設定 動畫的錨點。用於控制動畫縮放,放大,移動的中心點 //左上角 myview.layer.anchorPoint = CGPointMake(0, 0); //中心 myview.layer.anchorPoint = CGPointMake(0.5,0.5); //右下角 myview.layer.anchorPoint = CGPointMake(1, 1); */ [self.view addSubview:myview]; //關鍵幀 單一動畫 CAKeyframeAnimation *keyAnima1=[CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"
]; keyAnima1.duration =1; keyAnima1.values = @[@(0),@(M_PI/4),@(M_PI/2)]; keyAnima1.keyTimes = @[@0.0,@0.1,@1.0]; keyAnima1.fillMode=kCAFillModeForwards; keyAnima1.removedOnCompletion = NO; keyAnima1.repeatCount = 1;//或 keyAnima1.repeatDuration = 100; keyAnima1.beginTime = CACurrentMediaTime() + 1
; keyAnima1.timingFunction =[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; keyAnima1.delegate = self; [myview.layer addAnimation:keyAnima1 forKey:@"brushTransformAnimation"]; //關鍵幀 組合動畫 //旋轉動畫 CAKeyframeAnimation *keyAnima_group1=[CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"]; keyAnima_group1.values = @[@(M_PI/2),@(M_PI),@(M_PI * 2)];; //位置移動動畫 CAKeyframeAnimation *keyAnima_group2=[CAKeyframeAnimation animationWithKeyPath:@"position"]; NSValue *value1=[NSValue valueWithCGPoint:CGPointMake(myview.center.x,myview.center.y)]; NSValue *value2=[NSValue valueWithCGPoint:CGPointMake(200, 200)]; NSValue *value3=[NSValue valueWithCGPoint:CGPointMake(150, 150)]; keyAnima_group2.values= @[value1,value2,value3]; //組合兩個動畫 CAAnimationGroup * g = [CAAnimationGroup animation]; g.animations = @[keyAnima_group1,keyAnima_group2]; g.duration = 3; g.fillMode=kCAFillModeForwards; g.removedOnCompletion = NO; //再上一個動畫執行完 在執行 g.beginTime = CACurrentMediaTime() + 2; [myview.layer addAnimation:g forKey:@"g"]; //關鍵幀 單一動畫。設定關鍵幀的 path 而不是 value CAKeyframeAnimation * keyAnima2 = [CAKeyframeAnimation animationWithKeyPath:@"position"]; keyAnima2.calculationMode = kCAAnimationPaced; keyAnima2.fillMode = kCAFillModeForwards; keyAnima2.removedOnCompletion = NO; keyAnima2.duration = 2; keyAnima2.timingFunction =[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; keyAnima2.beginTime = CACurrentMediaTime() + 5; CGMutablePathRef curvedPath_3 = CGPathCreateMutable(); CGPathMoveToPoint(curvedPath_3, NULL, 150, 150); CGPathAddArc(curvedPath_3, NULL, 100, 150, 50, 0 , M_PI*2 , NO); keyAnima2.path = curvedPath_3; CGPathRelease(curvedPath_3); [myview.layer addAnimation:keyAnima2 forKey:@"moveTheSquare"];

基本屬性的說明

屬性 說明
KeyPath 動畫變化的屬性,如動畫的位置,大小,顏色的變化,詳見“表1”
duration 動畫執行的時間
repeatCount 重複次數,無限迴圈可以設定HUGE_VALF或者MAXFLOAT
repeatDuration a重複的時間
removedOnCompletion 預設為YES,代表動畫執行完畢後就從圖層上移除,圖形會恢復到動畫執行前的狀態。如果想讓圖層保持顯示動畫執行後的狀態,那就設定為NO,不過還要設定fillMode為kCAFillModeForwards
fillMode 決定當前物件在非active時間段的行為。比如動畫開始之前或者動畫結束之,詳見“表2”
beginTime 開始時間
timingFunction 速度控制函式,控制動畫執行的節奏 詳見“表3”
values NSArray物件。裡面的元素稱為“關鍵幀”(keyframe)。動畫物件會在指定的時間(duration)內,依次顯示values陣列中的每一個關鍵幀
keyTimes 可以為對應的關鍵幀指定對應的時間點,其取值範圍為0到1.0,例如keyAnima1.keyTimes = @[@0.0,@0.1,@0.5,@0.7,@1.0],keyTimes中的每一個時間值都對應values中的每一幀。如果沒有設定keyTimes,各個關鍵幀的時間是平分的,keyTimes 是和 values一起的。
path 可以設定一個CGPathRef、CGMutablePathRef,讓圖層按照路徑軌跡移動。path只對CALayer的anchorPoint和position起作用。如果設定了path,那麼values將被忽略
delegate 動畫代理,動畫開始 和 動畫完成

表1
KeyPath屬性的設定詳解:

屬性值 說明
transform.scale x,y軸同比放大縮小. 對應的
transform.scale.x x軸放大縮小
transform.scale.y y軸放大縮小
transform.rotation或transform.rotation.z 沿z軸旋轉
transform.rotation.x 沿x軸旋轉
transform.rotation.y 沿y軸旋轉
margin 邊距變化
backgroundColor 背景顏色變化
cornerRadius 圓角變化
borderWidth 變得寬度變化
bounds 大小變化
contents 內容變化
contentsRect 內容大小變化
frame 大小變化
hidden 是否顯示
mask mask層變化
masksToBounds ???(有知道的可以評論告訴我)
shadowColor 陰影顏色
shadowOffset 陰影位置
shadowOpacity 陰影透明度
shadowRadius 陰影圓角

備註:keyPath 對應的 “values” 陣列內大多數存的是 NSNumber 物件 。position ,frame 等 存的是 NSValue *value2=[NSValue valueWithCGPoint:CGPointMake(200, 200)]; 這樣的物件。


表2
fillMode屬性的設定詳解:

屬性值 說明
kCAFillModeRemoved 這個是預設值,也就是說當動畫開始前和動畫結束後,動畫對layer都沒有影響,動畫結束後,layer會恢復到之前的狀態
kCAFillModeForwards 當動畫結束後,layer會一直保持著動畫最後的狀態
kCAFillModeBackwards 在動畫開始前,只需要將動畫加入了一個layer,layer便立即進入動畫的初始狀態並等待動畫開始。
kCAFillModeBoth 這個其實就是上面兩個的合成.動畫加入後開始之前,layer便處於動畫初始狀態,動畫結束後layer保持動畫最後的狀態

表3
速度控制函式(CAMediaTimingFunction)設定詳解:

屬性值 說明
kCAMediaTimingFunctionLinear 線性,勻速,給你一個相對靜態的感覺
kCAMediaTimingFunctionEaseIn 漸進,動畫緩慢進入,然後加速離開
kCAMediaTimingFunctionEaseOut 漸出,動畫全速進入,然後減速的到達目的地
kCAMediaTimingFunctionEaseInEaseOut 漸進漸出,動畫緩慢的進入,中間加速,然後減速的到達目的地。這個是預設的動畫行為

動畫的代理方法

方法名 說明
– (void)animationDidStart:(CAAnimation *)anim; 動畫開始時呼叫
– (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag; 動畫結束時呼叫

CALayer上動畫的暫停和恢復

#pragma mark 暫停CALayer的動畫
-(void)pauseLayer:(CALayer*)layer
{
    CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];

    // 讓CALayer的時間停止走動
      layer.speed = 0.0;
    // 讓CALayer的時間停留在pausedTime這個時刻
    layer.timeOffset = pausedTime;
}

#pragma mark 恢復CALayer的動畫
-(void)resumeLayer:(CALayer*)layer
{
    CFTimeInterval pausedTime = layer.timeOffset;
    // 1. 讓CALayer的時間繼續行走
      layer.speed = 1.0;
    // 2. 取消上次記錄的停留時刻
      layer.timeOffset = 0.0;
    // 3. 取消上次設定的時間
      layer.beginTime = 0.0;
    // 4. 計算暫停的時間(這裡也可以用CACurrentMediaTime()-pausedTime)
    CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
    // 5. 設定相對於父座標系的開始時間(往後退timeSincePause)
      layer.beginTime = timeSincePause;
}