一、簡介
Core Animation,中文翻譯為核心動畫,它是一組非常強大的動畫處理API,使用它能做出非常炫麗的動畫效果,而且往往是事半功倍。也就是說,使用少量的代碼就可以實現非常強大的功能。
Core Animation是跨平臺的,可以用在Mac OS X和iOS平臺。
Core Animation的動畫執行過程都是在后臺操作的,不會阻塞主線程。不阻塞主線程,可以理解為在執行動畫的時候還能點擊(按鈕)。
要注意的是,Core Animation是直接作用在CALayer上的,并非UIView。
Core Animation的使用步驟
1.使用它需要先添加QuartzCore.framework框架和引入主頭文件(iOS7不需要)
2.初始化一個CAAnimation對象,并設置一些動畫相關屬性
3.通過調用CALayer的addAnimation:forKey:方法增加CAAnimation對象到CALayer中,這樣就能開始執行動畫了
4.通過調用CALayer的removeAnimationForKey:方法可以停止CALayer中的動畫
屬性及說明
CAAnimation是所有動畫類的父類,但是它不能直接使用,應該使用它的子類。
(1)能用的動畫類只有4個子類:CABasicAnimation(基礎動畫)、CAKeyframeAnimation(關鍵幀動畫)、CATransition(轉場動畫)、CAAnimationGroup(組動畫)
(2)CAMediaTiming是一個協議(protocol)。
CAPropertyAnimation是CAAnimation的子類,但是不能直接使用,要想創建動畫對象,應該使用它的兩個子類:CABasicAnimation(基礎動畫)和CAKeyframeAnimation(關鍵幀動畫)
屬性:((**)代表來自CAMediaTiming協議的屬性)
duration:(**)動畫的持續時間
repeatCount:(**)動畫的重復次數
repeatDuration:(**)動畫的重復時間
removedOnCompletion:默認為YES,代表動畫執行完畢后就從圖層上移除,圖形會恢復到動畫執行前的狀態。如果想讓圖層保持顯示動畫執行后的狀態,那就設置為NO,不過還要設置fillMode為kCAFillModeForwards
fillMode:(**)決定當前對象在非active時間段的行為.比如動畫開始之前,動畫結束之后
beginTime:(**)可以用來設置動畫延遲執行時間,若想延遲2s,就設置為CACurrentMediaTime()+2,CACurrentMediaTime()為圖層的當前時間
timingFunction:速度控制函數,控制動畫運行的節奏
delegate:動畫代理
二、基礎動畫 CABasicAnimation
CAPropertyAnimation的子類
屬性解析:
fromValue:keyPath相應屬性的初始值
toValue:keyPath相應屬性的結束值
隨著動畫的進行,在長度為duration的持續時間內,keyPath相應屬性的值從fromValue漸漸地變為toValue
如果fillMode=kCAFillModeForwards && removedOnComletion=NO,那么在動畫執行完畢后,圖層會保持顯示動畫執行后的狀態。但在實質上,圖層的屬性值還是動畫執行前的初始值,并沒有真正被改變。
比如,CALayer的position初始值為(0,0),CABasicAnimation的fromValue為(10,10),toValue為(100,100),雖然動畫執行完畢后圖層保持在(100,100)這個位置,實質上圖層的position還是為(0,0)
1、平移動畫
創建layer
CALayer *myLayer=[CALayer layer];
//設置layer的屬性
myLayer.bounds=CGRectMake(0, 0, 50, 80);
myLayer.backgroundColor=[UIColor yellowColor].CGColor;
myLayer.position=CGPointMake(50, 50);
myLayer.anchorPoint=CGPointMake(0, 0);
myLayer.cornerRadius=20;
//添加layer
[self.view.layer addSublayer:myLayer];
//設置動畫(基礎動畫)
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
//1.創建核心動畫
//? ? CABasicAnimation *anima=[CABasicAnimation animationWithKeyPath:<#(NSString *)#>]
CABasicAnimation *anima=[CABasicAnimation animation];
//1.1告訴系統要執行什么樣的動畫? 設置的keyPath是@"position",說明要修改的是CALayer的position屬性,也就是會執行平移動畫
anima.keyPath=@"position";
//設置通過動畫,將layer從哪兒移動到哪兒? 這里的屬性接收的時id類型的參數,因此并不能直接使用CGPoint這種結構體類型,而是要先包裝成NSValue對象后再使用。
//byValue和toValue的區別,byValue--是在當前的位置上增加多少,toValue--是移動到指定的位置。
anima.fromValue=[NSValue valueWithCGPoint:CGPointMake(0, 0)];
anima.toValue=[NSValue valueWithCGPoint:CGPointMake(200, 300)];
//1.2設置動畫執行完畢之后不刪除動畫
anima.removedOnCompletion=NO;
//1.3設置保存動畫的最新狀態
anima.fillMode=kCAFillModeForwards;
//2.添加核心動畫到layer
[myLayer addAnimation:anima forKey:nil];
}
設置代理:設置動畫的代理,可以監聽動畫的執行過程,這里設置控制器為代理。
-(void)animationDidStart:(CAAnimation *)anim{
NSLog(@"開始執行動畫");
}
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
//動畫執行完畢,打印執行完畢后的position值
NSString *str=NSStringFromCGPoint(self.myLayer.position);
NSLog(@"執行后:%@",str);//打印position的屬性值,驗證圖層的屬性值還是動畫執行前的初始值{50,50},并沒有真正被改變為{200,300}。
}
2、縮放動畫
//創建layer
CALayer *myLayer=[CALayer layer];
myLayer.bounds=CGRectMake(0, 0, 150, 60);
myLayer.backgroundColor=[UIColor yellowColor].CGColor;
myLayer.position=CGPointMake(50, 50);
myLayer.anchorPoint=CGPointMake(0, 0);
myLayer.cornerRadius=40;
[self.view.layer addSublayer:myLayer];
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
//1.創建動畫
CABasicAnimation *anima=[CABasicAnimation animationWithKeyPath:@"bounds"];
//1.1設置動畫執行時間
anima.duration=2.0;
//1.2設置動畫執行完畢后不刪除動畫
anima.removedOnCompletion=NO;
//1.3設置保存動畫的最新狀態
anima.fillMode=kCAFillModeForwards;
//1.4修改屬性,執行動畫
anima.toValue=[NSValue valueWithCGRect:CGRectMake(0, 0, 200, 200)];
//2.添加動畫到layer
[myLayer addAnimation:anima forKey:nil];
}
3、旋轉動畫
//創建layer(同縮放)
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
//1.創建動畫
CABasicAnimation *anima=[CABasicAnimation animationWithKeyPath:@"transform"];
//1.1設置動畫執行時間
anima.duration=2.0;
//1.2修改屬性,執行動畫? 如果要讓圖形以2D的方式旋轉,只需要把CATransform3DMakeRotation在z方向上的值改為1即可。
anima.toValue=[NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2+M_PI_4, 1, 1, 0)];
//1.3設置動畫執行完畢后不刪除動畫
anima.removedOnCompletion=NO;
//1.4設置保存動畫的最新狀態
anima.fillMode=kCAFillModeForwards;
//2.添加動畫到layer
[self.myLayer addAnimation:anima forKey:nil];
}
anima.toValue=[NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2+M_PI_4, 1, 1, 0)];
4、補充
4.1、可以通過transform(KVC)的方式來進行設置
4.2、fillMode的作用就是決定當前對象過了非active時間段的行為. 比如動畫開始之前,動畫結束之后。如果是一個動畫CAAnimation,則需要將其removedOnCompletion設置為NO,要不然fillMode不起作用.
各個fillMode的意義
kCAFillModeRemoved - 這個是默認值,也就是說當動畫開始前和動畫結束后,動畫對layer都沒有影響,動畫結束后,layer會恢復到之前的狀態
kCAFillModeForwards - 當動畫結束后,layer會一直保持著動畫最后的狀態
kCAFillModeBackwards - 這個和kCAFillModeForwards是相對的,就是在動畫開始前,你只要將動畫加入了一個layer,layer便立即進入動畫的初始狀態并等待動畫開始.你可以這樣設定測試代碼,將一個動畫加入一個layer的時候延遲5秒執行.然后就會發現在動畫沒有開始的時候,只要動畫被加入了layer,layer便處于動畫初始狀態
kCAFillModeBoth - 理解了上面兩個,這個就很好理解了,這個其實就是上面兩個的合成.動畫加入后開始之前,layer便處于動畫初始狀態,動畫結束后layer保持動畫最后的狀態.
三、關鍵幀動畫 CAKeyframeAnimation
1、簡介
CAKeyframeAnimation是CApropertyAnimation的子類,跟CABasicAnimation的區別是:CABasicAnimation只能從一個數值(fromValue)變到另一個數值(toValue),而CAKeyframeAnimation會使用一個NSArray保存這些數值
屬性解析:
values:就是上述的NSArray對象。里面的元素稱為”關鍵幀”(keyframe)。動畫對象會在指定的時間(duration)內,依次顯示values數組中的每一個關鍵幀
path:可以設置一個CGPathRef\CGMutablePathRef,讓層跟著路徑移動。path只對CALayer的anchorPoint和position起作用。如果你設置了path,那么values將被忽略
keyTimes:可以為對應的關鍵幀指定對應的時間點,其取值范圍為0到1.0,keyTimes中的每一個時間值都對應values中的每一幀.當keyTimes沒有設置的時候,各個關鍵幀的時間是平分的
說明:CABasicAnimation可看做是最多只有2個關鍵幀的CAKeyframeAnimation
2、平移
@property (nonatomic, strong) UIView *customView;
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
//1.創建核心動畫
CAKeyframeAnimation *keyAnima = [CAKeyframeAnimation animation];
keyAnima.keyPath = @"position";//平移
//1.1告訴系統要執行什么動畫
keyAnima.values = @[[NSValue valueWithCGPoint:CGPointMake(100, 100)],
[NSValue valueWithCGPoint:CGPointMake(200, 100)],
[NSValue valueWithCGPoint:CGPointMake(200, 200)],
[NSValue valueWithCGPoint:CGPointMake(100, 200)],
[NSValue valueWithCGPoint:CGPointMake(100, 100)]];
//1.2設置動畫執行完畢后,不刪除動畫? 默認為YES,代表動畫執行完畢后就從圖層上移除,圖形會恢復到動畫執行前的狀態。如果想讓圖層保持顯示動畫執行后的狀態,那就設置為NO,不過還要設置fillMode為kCAFillModeForwards
keyAnima.removedOnCompletion = NO;
//1.3設置保存動畫的最新狀態
keyAnima.fillMode = kCAFillModeForwards;
//1.4設置動畫執行的時間
keyAnima.duration = 4.0;
//1.5速度控制函數,控制動畫運行的節奏
keyAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
//設置代理,開始—結束
keyAnima.delegate = self;
//2.添加核心動畫
[self.customView.layer addAnimation:keyAnima forKey:nil];
//beginTime:可以用來設置動畫延遲執行時間,若想延遲2s,就設置為CACurrentMediaTime()+2,CACurrentMediaTime()為圖層的當前時間
}
-(void)animationDidStart:(CAAnimation *)anim{
NSLog(@"開始動畫"); }
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
NSLog(@"結束動畫"); }
1.5----
3、使用path,讓layer在指定的路徑上移動(畫圓)
//1.創建核心動畫
CAKeyframeAnimation *keyAnima=[CAKeyframeAnimation animation];
keyAnima.keyPath=@"position";//平移
//1.1告訴系統要執行什么動畫
//創建一條路徑
CGMutablePathRef path = CGPathCreateMutable();
//設置一個圓的路徑
CGPathAddEllipseInRect(path, NULL, CGRectMake(150, 100, 100, 100));
keyAnima.path = path; //可以通過path屬性,讓layer在指定的軌跡上運動。
//有create就一定要有release
CGPathRelease(path);
//1.2...1.5 同上
//2.添加核心動畫
[self.customView.layer addAnimation:keyAnima forKey:@"key"];
//3 動畫停止
- (void)stopOnClick:(UIButton *)button {
//停止self.customView.layer上名稱標示為key的動畫
[self.customView.layer removeAnimationForKey:@"key"];
//[self.customView.layer removeAllAnimations];//移除全部動畫
}
4、抖動(旋轉)
#define angle2Radian(angle)? ((angle)/180.0*M_PI)
//1.創建核心動畫
CAKeyframeAnimation *keyAnima = [CAKeyframeAnimation animation];
keyAnima.keyPath = @"transform.rotation";//旋轉
//設置動畫時間
keyAnima.duration = 0.1;
//設置圖標抖動弧度
//把度數轉換為弧度? 度數/180*M_PI
keyAnima.values = @[@(-angle2Radian(4)), @(angle2Radian(4)), @(-angle2Radian(4))];//向左向右偏轉一個弧度(4),產生抖動的視覺效果
//設置動畫的重復次數(設置為最大值)
keyAnima.repeatCount = MAXFLOAT;
keyAnima.fillMode = kCAFillModeForwards;
keyAnima.removedOnCompletion = NO;
//2.添加動畫
[self.iconView.layer addAnimation:keyAnima forKey:nil];
四、轉場動畫 CATransition
CAAnimation的子類,用于做轉場動畫,能夠為層提供移出屏幕和移入屏幕的動畫效果。iOS比Mac OS X的轉場動畫效果少一點
UINavigationController就是通過CATransition實現了將控制器的視圖推入屏幕的動畫效果
屬性解析:
type:動畫過渡類型
subtype:動畫過渡方向
startProgress:動畫起點(在整體動畫的百分比)
endProgress:動畫終點(在整體動畫的百分比)
1、界面
2、代碼
@property(nonatomic,assign)intindex;
@property (nonatomic, strong) UIImageView *iconView;
- (IBAction)preOnClick:(UIButton *)sender;
- (IBAction)nextOnClick:(UIButton *)sender;
- (void)viewDidLoad{
[super viewDidLoad];
self.index=1;
}
//上一張
- (IBAction)preOnClick:(UIButton *)sender {
self.index--;
if (self.index<1) {
self.index=7;
}
self.iconView.image=[UIImage imageNamed: [NSString stringWithFormat:@"%d.jpg",self.index]];
//創建核心動畫
CATransition *ca=[CATransition animation];
//告訴要執行什么動畫
//設置過度效果
ca.type=@"cube";
//設置動畫的過度方向(向左)
ca.subtype=kCATransitionFromLeft;
//設置動畫的時間
ca.duration=2.0;
//添加動畫
[self.iconView.layer addAnimation:ca forKey:nil];? }
//下一張
- (IBAction)nextOnClick:(UIButton *)sender {
self.index++;
if (self.index>7) {
self.index=1;
}
self.iconView.image=[UIImage imageNamed: [NSString stringWithFormat:@"%d.jpg",self.index]];
//1.創建核心動畫
CATransition *ca=[CATransition animation];
//1.1告訴要執行什么動畫
//1.2設置過度效果
ca.type=@"cube";
//1.3設置動畫的過度方向(向右)
ca.subtype=kCATransitionFromRight;
//1.4設置動畫的時間
ca.duration=2.0;
//1.5設置動畫的起點
ca.startProgress=0.5;
//1.6設置動畫的終點
//? ? ca.endProgress=0.5;
//2.添加動畫
[self.iconView.layer addAnimation:ca forKey:nil]; }
五、組動畫 CAAnimationGroup
1、簡介
CAAnimation的子類,可以保存一組動畫對象,將CAAnimationGroup對象加入層后,組中所有動畫對象可以同時并發運行
屬性解析:
animations:用來保存一組動畫對象的NSArray
默認情況下,一組動畫對象是同時運行的,也可以通過設置動畫對象的beginTime屬性來更改動畫的開始時間
2、代碼
// 平移動畫
CABasicAnimation *a1 = [CABasicAnimation animation];
a1.keyPath = @"transform.translation.y";
a1.toValue = @(100);
// 縮放動畫
CABasicAnimation *a2 = [CABasicAnimation animation];
a2.keyPath = @"transform.scale";
a2.toValue = @(0.0);
// 旋轉動畫
CABasicAnimation *a3 = [CABasicAnimation animation];
a3.keyPath = @"transform.rotation";
a3.toValue = @(M_PI_2);
// 組動畫
CAAnimationGroup *groupAnima = [CAAnimationGroup animation];
groupAnima.animations = @[a1, a2, a3];
//設置組動畫的時間
groupAnima.duration = 2;
groupAnima.fillMode = kCAFillModeForwards;
groupAnima.removedOnCompletion = NO;
[self.iconView.layer addAnimation:groupAnima forKey:nil];