每個UIView都有關(guān)聯(lián)的CALayer對象,被稱之為rootLayer宋光。
隱式動畫
隱式動畫指我們沒有指定任何動畫類型迫淹,只是改變了layer的屬性,有框架自動完成動畫效果铺浇,默認持續(xù)時間是0.25s痢畜;但是只有非rootLayer(自己創(chuàng)建的)才有隱式動畫,具體原因如下:
我們把改變屬性時CALayer自動應(yīng)用的動畫稱作action鳍侣,當CALayer的屬性被修改時候裁着,它會調(diào)用
actionForKey:
方法,傳遞屬性的名稱拱她。具體見如下步驟:
- 圖層首先檢測它是否有委托,并且是否實現(xiàn)CALayerDelegate協(xié)議指定的
actionForLayer:forKey
方法扔罪。如果有秉沼,直接調(diào)用并返回結(jié)果。 - 如果沒有委托矿酵,或者委托沒有實現(xiàn)-actionForLayer:forKey方法唬复,圖層接著檢查包含屬性名稱對應(yīng)行為映射的actions字典。
- 如果actions字典沒有包含對應(yīng)的屬性全肮,那么圖層接著在它的style字典接著搜索屬性名敞咧。
- 最后,如果在style里面也找不到對應(yīng)的行為辜腺,那么圖層將會直接調(diào)用定義了每個屬性的標準行為的-defaultActionForKey:方法休建。
在一輪完整的搜索結(jié)束之后,-actionForKey:要么返回空(這種情況下將不會有動畫發(fā)生)评疗,要么返回CAAction協(xié)議的對象测砂,最后CALayer拿這個結(jié)果去做動畫。
每個UIView對它關(guān)聯(lián)的圖層都扮演了一個委托百匆,并且提供了-actionForLayer:forKey的實現(xiàn)方法砌些。當不在一個動畫塊的實現(xiàn)中,UIView對所有圖層行為返回nil加匈,但是在動畫block范圍之內(nèi)存璃,它就返回了一個非空值。
NSLog(@"Outside: %@", [self.view actionForLayer:self.view.layer forKey:@"backgroundColor"]);
//begin animation block
[UIView beginAnimations:nil context:nil];
//test layer action when inside of animation block
NSLog(@"Inside: %@", [self.view actionForLayer:self.view.layer forKey:@"backgroundColor"]);
//end animation block
[UIView commitAnimations];
打印結(jié)果如下
Outside: <null>
Inside: <CABasicAnimation: 0x7ff3e9d28f40>
具體可見官方文檔
在objc中View-Layer 協(xié)作也有說明
- Layer可動畫屬性 雕拼,如
- bounds:用于設(shè)置CALayer的寬度和高度纵东,修改這個屬性會產(chǎn)生縮放動畫;
- backgroundColor:用于設(shè)置CALayer的背景色啥寇,修改這個屬性會產(chǎn)生背景色的漸變動畫篮迎;
- position:用于設(shè)置CALayer的位置男图,修改這個屬性會產(chǎn)生平移動畫等等,可以在CALayer的頭文件中看到
- 利用CATransaction來改變默認的隱式動畫
CATransaction
說明
[CATransaction begin];
[CATransaction setAnimationDuration:1.0];
self.colorLayer.backgroundColor = [[UIColor yellowColor] CGColor];
[CATransaction commit];
顯式動畫
- 屬性動畫:作用于圖層的某個單一屬性甜橱,并指定了它的一個目標值逊笆,或者一連串將要做動畫的值。
- 動畫組:將多個屬性動畫組合到一起岂傲。
-
動畫過渡:不像屬性動畫那樣平滑地在兩個值之間做動畫难裆,而是影響到整個圖層的變化;過渡動畫首先展示之前的圖層樣子镊掖,然后過渡到新的樣子乃戈。
先來介紹屬性動畫下基礎(chǔ)動畫
CABasicAnimation
1.先看一個實現(xiàn)平移動畫的??
CALayer *layer = [[CALayer alloc]init];
layer.backgroundColor = [[UIColor grayColor]CGColor];
layer.frame = CGRectMake(40, 20, 40, 40);
layer.cornerRadius = 5;
[self.view.layer addSublayer:layer];
//平移動畫
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
animation.duration = 3.0;
animation.autoreverses = YES;
animation.repeatCount = HUGE_VALF;
animation.fromValue = [NSValue valueWithCGPoint:layer.position];
CGPoint toPoint = layer.position;
toPoint.x = toPoint.x+180;
animation.toValue = [NSValue valueWithCGPoint:toPoint];
[layer addAnimation:animation forKey:@"move"];
先是新建了一個layer,然后利用keyPath創(chuàng)建了一個動畫亩进,通過設(shè)置屬性定義動畫效果症虑,最后將動畫添加到layer上。
keyPath的值归薛,這邊列出比較常用谍憔,還有一些和上面敘述的layer的屬性類似
keyPath的值 | 說明 |
---|---|
position | 位置變化,引起平移動畫 |
transform.scale | 比例變化主籍,放大縮小 |
transform.scale.x | 寬度縮放 |
transform.scale.y | 高度縮放 |
transform.rotation | 旋轉(zhuǎn) |
transform.rotation.x | 沿x軸旋轉(zhuǎn) |
transform.rotation.y | 沿y軸旋轉(zhuǎn) |
transform.rotation.z | 沿z軸旋轉(zhuǎn) |
opacity | 透明度 |
backgroundColor | 背景顏色 |
cornerRadius | 圓角 |
animation的屬性
屬性 | 說明 |
---|---|
fromValue | 動畫改變的屬性初始值 |
toValue | 動畫改變的屬性結(jié)束值 |
byValue | 過程中屬性相對初始值改變的值 |
duration | 動畫持續(xù)時長 |
repeatCount | 動畫重復(fù)次數(shù)习贫,不停重復(fù)設(shè)置為 HUGE_VALF |
repeatDuration | 動畫應(yīng)該被重復(fù)多久,動畫會一直重復(fù)千元,直到設(shè)定的時間流逝完苫昌;它不應(yīng)該和 repeatCount 一起使用。 |
autoreverses | 動畫結(jié)束時是否執(zhí)行逆動畫幸海,當你設(shè)定這個屬性為 YES 時祟身,在它到達目的地之后,動畫的返回到開始的值物独,代替了直接跳轉(zhuǎn)到 開始的值月而。 |
beginTime | 指定動畫開始的時間。從開始延遲幾秒的話议纯,設(shè)置為【CACurrentMediaTime() + 秒數(shù)】 的方式 |
timingFunction | 設(shè)置動畫的速度變化父款,這個略復(fù)雜,稍候介紹 |
2.如果要定義動畫開始之前或結(jié)束之后的狀態(tài)瞻凤,可以用fillMode憨攒;不過要注意要在CABasicAnimation 中fillMode啟作用,需要將removedOnCompletion設(shè)為NO阀参,具體見CABasicAnimation fillMode和removedOnCompletion
scaleAnimation.removedOnCompletion = NO;
scaleAnimation.fillMode = kCAFillModeForwards;
解釋:為什么動畫結(jié)束后返回原狀態(tài)肝集?
layer有兩個重要屬性modelLayer和presentationLayer(還有一個renderingLayer,是私有的)蛛壳;modelLayer表現(xiàn)了我們看到的layer狀態(tài)杏瞻,當改變layer的屬性值所刀,modelLayer的屬性值也即刻改變;presentationLayer則表現(xiàn)的是動畫過程中狀態(tài)值捞挥。
而當我們給一個layer添加動畫時浮创,動畫開始時 presentation layer在不斷變化,動畫結(jié)束時砌函,presentation layer從屏幕上移除斩披,原始layer顯示。如果沒有改變過modelLayer的值讹俊,那么在動畫結(jié)束之后就會返回到原狀態(tài)垦沉。
3.其他例子
//旋轉(zhuǎn)動畫
CABasicAnimation *rotateAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.x"];
rotateAnimation.duration = 3.0;
rotateAnimation.repeatCount = HUGE_VALF;
rotateAnimation.autoreverses = YES;
rotateAnimation.fromValue = [NSNumber numberWithFloat:0];
rotateAnimation.toValue = [NSNumber numberWithFloat:6*M_PI];
[rotateLayer addAnimation:rotateAnimation forKey:@"rotate"];
//....
//放大、縮小
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale.x"];
scaleAnimation.duration = 3.0;
scaleAnimation.repeatCount = HUGE_VALF;
scaleAnimation.autoreverses = YES;
scaleAnimation.removedOnCompletion = NO;
scaleAnimation.fromValue = [NSNumber numberWithFloat:1.0];
scaleAnimation.toValue = [NSNumber numberWithFloat:2.5];
scaleAnimation.fillMode = kCAFillModeForwards;
[scaleLayer addAnimation:scaleAnimation forKey:@"scale"];
參考資料
core animation官方文檔
淺談animation
CABasicAnimation使用總結(jié)
顯式動畫
隱式動畫
讓你的動畫動起來