CATransaction事務
<br />
CALayer的"Animatable"屬性的設置都應該屬于某一個CATransaction事務,CATransaction的作用是保證多個"Animatable"的變化同時進行。也就是說CALayer的屬性改變需要依賴CATransaction。
CATransaction也分為隱式和顯示。
隱式:在某次RunLoop中設置了一個"Animatable"屬性,如果當前沒有設置事務,則會自動創建一個CATransaction,并在當前線程的下一個RunLoop中commit這個CATransaction。
顯示: 就是直接調用CATransaction的[CATransaction begin]
,[CATransaction commit]
等相關方法。比如我們不希望self.subLayer.position = CGPointMake(100,100)
產生動畫,則可以在CATransaction中設置 setDisableActions: YES
另外事務可以嵌套,當事務嵌套時,只有最外層的事務commit之后,整個動畫才開始。
<br />
自定義CALayer
<br />
自定義Layer有兩種方法:
- 通過delegate,在delegate里面實現layer內容的繪制及渲染
// 方法一
CALayer *customerLayer = [CALayer layer];
customerLayer.bounds = CGRectMake(0, 0, 200, 200);
customerLayer.position = CGPointMake(self.view.frame.size.width * 0.5, self.view.frame.size.height * 0.5);
customerLayer.backgroundColor = [UIColor redColor].CGColor;
customerLayer.delegate = self;
// - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx 該代理方法不會自動調用 必須主動調用setNeedDisplay方法才會觸發
[customerLayer setNeedsDisplay];
[self.view.layer addSublayer:customerLayer];
代理方法
#pragma mark - layer delegate
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
CGContextAddEllipseInRect(ctx, CGRectMake(0, 0, 100, 100));
CGContextSetRGBFillColor(ctx, 0, 1, 0, 1);
CGContextFillPath(ctx);
}
- 通過override自定義layer里面的
- (void)drawInContext:(CGContextRef)ctx
// 方法二
WYLayer *customerLayer = [WYLayer layer];
customerLayer.bounds = CGRectMake(0, 0, 200, 200);
customerLayer.position = CGPointMake(self.view.frame.size.width * 0.5, self.view.frame.size.height * 0.5);
// - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx 該代理方法不會自動調用 必須主動調用setNeedDisplay方法才會觸發
[customerLayer setNeedsDisplay];
[self.view.layer addSublayer:customerLayer];
自定義WYLayer
#import "WYLayer.h"
@implementation WYLayer
// 重寫該方法, 在該方法中給layer上繪制圖形
// 注意CALayer中的drawInContext方法, 不會自動調用
// 只能自己通過setNeedDisplay方法調用
- (void)drawInContext:(CGContextRef)ctx {
CGContextAddEllipseInRect(ctx, CGRectMake(0, 0, 100, 100));
// Attention:不能用UIKit框架中的類
// [[UIColor redColor] set];
CGContextSetRGBFillColor(ctx, 0, 1, 0, 1);
CGContextFillPath(ctx);
}
@end
<br />
CABaseAnimation
CAPropertyAnimation的子類
屬性解析:
fromValue:keyPath
相應屬性的初始值
toValue:keyPath
相應屬性的結束值
隨著動畫的進行,在長度為duration
的持續時間內,keyPath
相應屬性的值從fromValue
漸漸地變為toValue
Attention:如果fillMode=kCAFillModeForwards和removedOnComletion=NO
,那么在動畫執行完畢后,圖層會保持顯示動畫執行后的狀態。但在實質上,圖層的屬性值還是動畫執行前的初始值,并沒有真正被改變。比如,CALayer的position
初始值為(0,0),CABasicAnimation的fromValue
為(10,10),toValue
為(100,100),雖然動畫執行完畢后圖層保持在(100,100)這個位置,實質上圖層的position
還是為(0,0)
// 創建基本動畫
CABasicAnimation *animation = [CABasicAnimation animation];
// 設置動畫類型
animation.keyPath = @"transform";
// 設置動畫結束后不刪除動畫
animation.removedOnCompletion = NO;
// 設置動畫結束后的最新狀態
animation.fillMode = kCAFillModeForwards;
// 設置動畫時長
animation.duration = 4;
// 設置移動位置
animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2, 0, 0, 1)];
[self.myLayer addAnimation:animation forKey:nil];
<br />
CAKeyFrameAnimation
CApropertyAnimation的子類,跟CABasicAnimation的區別是:CABasicAnimation只能從一個數值fromValue
變到另一個數值toValue
,而CAKeyframeAnimation會使用一個NSArray保存這些數值。
屬性解析:
values:就是上述的NSArray對象。里面的元素稱為”關鍵幀”(keyframe)。動畫對象會在指定的時間duration
內,依次顯示values
數組中的每一個關鍵幀
path:可以設置一個CGPathRef\CGMutablePathRef
,讓層跟著路徑移動。path
只對CALayer的anchorPoint
和position
起作用。<u>如果你設置了path
,那么values
將被忽略</u>。
keyTimes:可以為對應的關鍵幀指定對應的時間點,其取值范圍為0到1.0,keyTimes中的每一個時間值都對應values中的每一幀.當keyTimes沒有設置的時候,各個關鍵幀的時間是平分的。
CABasicAnimation可看做是最多只有2個關鍵幀的CAKeyframeAnimation。
關鍵幀動畫的創建可以有兩種方式:
values
// 1.創建核心動畫
CAKeyframeAnimation *keyAnima = [CAKeyframeAnimation animation];
// 1.1告訴系統執行什么動畫
keyAnima.keyPath = @"position";
// NSValue *v1 = [NSValue valueWithCGPoint:CGPointMake(0, 100)];
NSValue *v2 = [NSValue valueWithCGPoint:CGPointMake(100, 100)];
NSValue *v3 = [NSValue valueWithCGPoint:CGPointMake(100, 200)];
NSValue *v4 = [NSValue valueWithCGPoint:CGPointMake(0, 200)];
NSValue *v5 = [NSValue valueWithCGPoint:CGPointMake(0, 100)];
keyAnima.values = @[v2, v3, v4, v5];
// keyAnima.keyTimes = @[@(0.5) ,@(0.5), @(0.5)];
keyAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
// 1.2保存執行完之后的狀態
// 1.2.1執行完之后不刪除動畫
keyAnima.removedOnCompletion = NO;
// 1.2.2執行完之后保存最新的狀態
keyAnima.fillMode = kCAFillModeForwards;
// 1.3設置動畫時間
keyAnima.duration = 2;
// 2.觀察動畫什么時候開始執行, 以及什么時候執行完畢
keyAnima.delegate = self;
// 2.添加核心動畫
[self.customView.layer addAnimation:keyAnima forKey:nil];
path
// 1.創建核心動畫
CAKeyframeAnimation *keyAnima = [CAKeyframeAnimation animation];
// 1.1告訴系統執行什么動畫
keyAnima.keyPath = @"position";
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddEllipseInRect(path, NULL, CGRectMake(0, 100, 200, 200));
keyAnima.path = path;
CGPathRelease(path);
// 1.2保存執行完之后的狀態
// 1.2.1執行完之后不刪除動畫
keyAnima.removedOnCompletion = NO;
// 1.2.2執行完之后保存最新的狀態
keyAnima.fillMode = kCAFillModeForwards;
// 1.3設置動畫時間
keyAnima.duration = 2;
// 2.觀察動畫什么時候開始執行, 以及什么時候執行完畢
keyAnima.delegate = self;
// 3.添加核心動畫
[self.customView.layer addAnimation:keyAnima forKey:@"abc"];