一、簡(jiǎn)介
Core Animation攻柠,中文翻譯為核心動(dòng)畫,它是一組非常強(qiáng)大的動(dòng)畫處理API后裸,使用它能做出非常炫麗的動(dòng)畫效果瑰钮,而且往往是事半功倍。也就是說微驶,使用少量的代碼就可以實(shí)現(xiàn)非常強(qiáng)大的功能浪谴。
Core Animation是跨平臺(tái)的,可以用在Mac OS X和iOS平臺(tái)因苹。
Core Animation的動(dòng)畫執(zhí)行過程都是在后臺(tái)操作的较店,不會(huì)阻塞主線程。不阻塞主線程容燕,可以理解為在執(zhí)行動(dòng)畫的時(shí)候還能點(diǎn)擊(按鈕)。
要注意的是婚度,Core Animation是直接作用在CALayer上的蘸秘,并非UIView官卡。
Core Animation的使用步驟
1.使用它需要先添加QuartzCore.framework框架和引入主頭文件(iOS7不需要)
2.初始化一個(gè)CAAnimation對(duì)象,并設(shè)置一些動(dòng)畫相關(guān)屬性
3.通過調(diào)用CALayer的addAnimation:forKey:方法增加CAAnimation對(duì)象到CALayer中醋虏,這樣就能開始執(zhí)行動(dòng)畫了
4.通過調(diào)用CALayer的removeAnimationForKey:方法可以停止CALayer中的動(dòng)畫
屬性及說明
CAAnimation是所有動(dòng)畫類的父類寻咒,但是它不能直接使用,應(yīng)該使用它的子類颈嚼。
(1)能用的動(dòng)畫類只有4個(gè)子類:CABasicAnimation(基礎(chǔ)動(dòng)畫)毛秘、CAKeyframeAnimation(關(guān)鍵幀動(dòng)畫)、CATransition(轉(zhuǎn)場(chǎng)動(dòng)畫)阻课、CAAnimationGroup(組動(dòng)畫)
(2)CAMediaTiming是一個(gè)協(xié)議(protocol)叫挟。
CAPropertyAnimation是CAAnimation的子類,但是不能直接使用限煞,要想創(chuàng)建動(dòng)畫對(duì)象抹恳,應(yīng)該使用它的兩個(gè)子類:CABasicAnimation(基礎(chǔ)動(dòng)畫)和CAKeyframeAnimation(關(guān)鍵幀動(dòng)畫)
屬性:((**)代表來自CAMediaTiming協(xié)議的屬性)
duration:(**)動(dòng)畫的持續(xù)時(shí)間
repeatCount:(**)動(dòng)畫的重復(fù)次數(shù)
repeatDuration:(**)動(dòng)畫的重復(fù)時(shí)間
removedOnCompletion:默認(rèn)為YES,代表動(dòng)畫執(zhí)行完畢后就從圖層上移除署驻,圖形會(huì)恢復(fù)到動(dòng)畫執(zhí)行前的狀態(tài)奋献。如果想讓圖層保持顯示動(dòng)畫執(zhí)行后的狀態(tài),那就設(shè)置為NO旺上,不過還要設(shè)置fillMode為kCAFillModeForwards
fillMode:(**)決定當(dāng)前對(duì)象在非active時(shí)間段的行為.比如動(dòng)畫開始之前,動(dòng)畫結(jié)束之后
beginTime:(**)可以用來設(shè)置動(dòng)畫延遲執(zhí)行時(shí)間瓶蚂,若想延遲2s,就設(shè)置為CACurrentMediaTime()+2宣吱,CACurrentMediaTime()為圖層的當(dāng)前時(shí)間
timingFunction:速度控制函數(shù)窃这,控制動(dòng)畫運(yùn)行的節(jié)奏
delegate:動(dòng)畫代理
二、基礎(chǔ)動(dòng)畫 CABasicAnimation
CAPropertyAnimation的子類
屬性解析:
fromValue:keyPath相應(yīng)屬性的初始值
toValue:keyPath相應(yīng)屬性的結(jié)束值
隨著動(dòng)畫的進(jìn)行凌节,在長(zhǎng)度為duration的持續(xù)時(shí)間內(nèi)钦听,keyPath相應(yīng)屬性的值從fromValue漸漸地變?yōu)閠oValue
如果fillMode=kCAFillModeForwards && removedOnComletion=NO,那么在動(dòng)畫執(zhí)行完畢后倍奢,圖層會(huì)保持顯示動(dòng)畫執(zhí)行后的狀態(tài)朴上。但在實(shí)質(zhì)上,圖層的屬性值還是動(dòng)畫執(zhí)行前的初始值卒煞,并沒有真正被改變痪宰。
比如,CALayer的position初始值為(0,0)畔裕,CABasicAnimation的fromValue為(10,10)衣撬,toValue為(100,100),雖然動(dòng)畫執(zhí)行完畢后圖層保持在(100,100)這個(gè)位置扮饶,實(shí)質(zhì)上圖層的position還是為(0,0)
1具练、平移動(dòng)畫
創(chuàng)建layer
CALayer *myLayer=[CALayer layer];
//設(shè)置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];
//設(shè)置動(dòng)畫(基礎(chǔ)動(dòng)畫)
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
//1.創(chuàng)建核心動(dòng)畫
//? ? CABasicAnimation *anima=[CABasicAnimation animationWithKeyPath:<#(NSString *)#>]
CABasicAnimation *anima=[CABasicAnimation animation];
//1.1告訴系統(tǒng)要執(zhí)行什么樣的動(dòng)畫? 設(shè)置的keyPath是@"position",說明要修改的是CALayer的position屬性甜无,也就是會(huì)執(zhí)行平移動(dòng)畫
anima.keyPath=@"position";
//設(shè)置通過動(dòng)畫扛点,將layer從哪兒移動(dòng)到哪兒? 這里的屬性接收的時(shí)id類型的參數(shù)哥遮,因此并不能直接使用CGPoint這種結(jié)構(gòu)體類型,而是要先包裝成NSValue對(duì)象后再使用陵究。
//byValue和toValue的區(qū)別眠饮,byValue--是在當(dāng)前的位置上增加多少,toValue--是移動(dòng)到指定的位置铜邮。
anima.fromValue=[NSValue valueWithCGPoint:CGPointMake(0, 0)];
anima.toValue=[NSValue valueWithCGPoint:CGPointMake(200, 300)];
//1.2設(shè)置動(dòng)畫執(zhí)行完畢之后不刪除動(dòng)畫
anima.removedOnCompletion=NO;
//1.3設(shè)置保存動(dòng)畫的最新狀態(tài)
anima.fillMode=kCAFillModeForwards;
//2.添加核心動(dòng)畫到layer
[myLayer addAnimation:anima forKey:nil];
}
設(shè)置代理:設(shè)置動(dòng)畫的代理仪召,可以監(jiān)聽動(dòng)畫的執(zhí)行過程,這里設(shè)置控制器為代理松蒜。
-(void)animationDidStart:(CAAnimation *)anim{
NSLog(@"開始執(zhí)行動(dòng)畫");
}
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
//動(dòng)畫執(zhí)行完畢扔茅,打印執(zhí)行完畢后的position值
NSString *str=NSStringFromCGPoint(self.myLayer.position);
NSLog(@"執(zhí)行后:%@",str);//打印position的屬性值,驗(yàn)證圖層的屬性值還是動(dòng)畫執(zhí)行前的初始值{50牍鞠,50}咖摹,并沒有真正被改變?yōu)閧200,300}难述。
}
2萤晴、縮放動(dòng)畫
//創(chuàng)建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.創(chuàng)建動(dòng)畫
CABasicAnimation *anima=[CABasicAnimation animationWithKeyPath:@"bounds"];
//1.1設(shè)置動(dòng)畫執(zhí)行時(shí)間
anima.duration=2.0;
//1.2設(shè)置動(dòng)畫執(zhí)行完畢后不刪除動(dòng)畫
anima.removedOnCompletion=NO;
//1.3設(shè)置保存動(dòng)畫的最新狀態(tài)
anima.fillMode=kCAFillModeForwards;
//1.4修改屬性,執(zhí)行動(dòng)畫
anima.toValue=[NSValue valueWithCGRect:CGRectMake(0, 0, 200, 200)];
//2.添加動(dòng)畫到layer
[myLayer addAnimation:anima forKey:nil];
}
3胁后、旋轉(zhuǎn)動(dòng)畫
//創(chuàng)建layer(同縮放)
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
//1.創(chuàng)建動(dòng)畫
CABasicAnimation *anima=[CABasicAnimation animationWithKeyPath:@"transform"];
//1.1設(shè)置動(dòng)畫執(zhí)行時(shí)間
anima.duration=2.0;
//1.2修改屬性店读,執(zhí)行動(dòng)畫? 如果要讓圖形以2D的方式旋轉(zhuǎn),只需要把CATransform3DMakeRotation在z方向上的值改為1即可攀芯。
anima.toValue=[NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2+M_PI_4, 1, 1, 0)];
//1.3設(shè)置動(dòng)畫執(zhí)行完畢后不刪除動(dòng)畫
anima.removedOnCompletion=NO;
//1.4設(shè)置保存動(dòng)畫的最新狀態(tài)
anima.fillMode=kCAFillModeForwards;
//2.添加動(dòng)畫到layer
[self.myLayer addAnimation:anima forKey:nil];
}
anima.toValue=[NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2+M_PI_4, 1, 1, 0)];
4屯断、補(bǔ)充
4.1、可以通過transform(KVC)的方式來進(jìn)行設(shè)置
4.2侣诺、fillMode的作用就是決定當(dāng)前對(duì)象過了非active時(shí)間段的行為. 比如動(dòng)畫開始之前,動(dòng)畫結(jié)束之后殖演。如果是一個(gè)動(dòng)畫CAAnimation,則需要將其removedOnCompletion設(shè)置為NO,要不然fillMode不起作用.
各個(gè)fillMode的意義
kCAFillModeRemoved - 這個(gè)是默認(rèn)值,也就是說當(dāng)動(dòng)畫開始前和動(dòng)畫結(jié)束后,動(dòng)畫對(duì)layer都沒有影響,動(dòng)畫結(jié)束后,layer會(huì)恢復(fù)到之前的狀態(tài)
kCAFillModeForwards - 當(dāng)動(dòng)畫結(jié)束后,layer會(huì)一直保持著動(dòng)畫最后的狀態(tài)
kCAFillModeBackwards - 這個(gè)和kCAFillModeForwards是相對(duì)的,就是在動(dòng)畫開始前,你只要將動(dòng)畫加入了一個(gè)layer,layer便立即進(jìn)入動(dòng)畫的初始狀態(tài)并等待動(dòng)畫開始.你可以這樣設(shè)定測(cè)試代碼,將一個(gè)動(dòng)畫加入一個(gè)layer的時(shí)候延遲5秒執(zhí)行.然后就會(huì)發(fā)現(xiàn)在動(dòng)畫沒有開始的時(shí)候,只要?jiǎng)赢嫳患尤肓薼ayer,layer便處于動(dòng)畫初始狀態(tài)
kCAFillModeBoth - 理解了上面兩個(gè),這個(gè)就很好理解了,這個(gè)其實(shí)就是上面兩個(gè)的合成.動(dòng)畫加入后開始之前,layer便處于動(dòng)畫初始狀態(tài),動(dòng)畫結(jié)束后layer保持動(dòng)畫最后的狀態(tài).
三、關(guān)鍵幀動(dòng)畫 CAKeyframeAnimation
1年鸳、簡(jiǎn)介
CAKeyframeAnimation是CApropertyAnimation的子類趴久,跟CABasicAnimation的區(qū)別是:CABasicAnimation只能從一個(gè)數(shù)值(fromValue)變到另一個(gè)數(shù)值(toValue),而CAKeyframeAnimation會(huì)使用一個(gè)NSArray保存這些數(shù)值
屬性解析:
values:就是上述的NSArray對(duì)象搔确。里面的元素稱為”關(guān)鍵幀”(keyframe)彼棍。動(dòng)畫對(duì)象會(huì)在指定的時(shí)間(duration)內(nèi),依次顯示values數(shù)組中的每一個(gè)關(guān)鍵幀
path:可以設(shè)置一個(gè)CGPathRef\CGMutablePathRef,讓層跟著路徑移動(dòng)膳算。path只對(duì)CALayer的anchorPoint和position起作用座硕。如果你設(shè)置了path,那么values將被忽略
keyTimes:可以為對(duì)應(yīng)的關(guān)鍵幀指定對(duì)應(yīng)的時(shí)間點(diǎn),其取值范圍為0到1.0,keyTimes中的每一個(gè)時(shí)間值都對(duì)應(yīng)values中的每一幀.當(dāng)keyTimes沒有設(shè)置的時(shí)候,各個(gè)關(guān)鍵幀的時(shí)間是平分的
說明:CABasicAnimation可看做是最多只有2個(gè)關(guān)鍵幀的CAKeyframeAnimation
2涕蜂、平移
@property (nonatomic, strong) UIView *customView;
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
//1.創(chuàng)建核心動(dòng)畫
CAKeyframeAnimation *keyAnima = [CAKeyframeAnimation animation];
keyAnima.keyPath = @"position";//平移
//1.1告訴系統(tǒng)要執(zhí)行什么動(dòng)畫
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設(shè)置動(dòng)畫執(zhí)行完畢后华匾,不刪除動(dòng)畫? 默認(rèn)為YES,代表動(dòng)畫執(zhí)行完畢后就從圖層上移除机隙,圖形會(huì)恢復(fù)到動(dòng)畫執(zhí)行前的狀態(tài)蜘拉。如果想讓圖層保持顯示動(dòng)畫執(zhí)行后的狀態(tài)刊头,那就設(shè)置為NO,不過還要設(shè)置fillMode為kCAFillModeForwards
keyAnima.removedOnCompletion = NO;
//1.3設(shè)置保存動(dòng)畫的最新狀態(tài)
keyAnima.fillMode = kCAFillModeForwards;
//1.4設(shè)置動(dòng)畫執(zhí)行的時(shí)間
keyAnima.duration = 4.0;
//1.5速度控制函數(shù)诸尽,控制動(dòng)畫運(yùn)行的節(jié)奏
keyAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
//設(shè)置代理,開始—結(jié)束
keyAnima.delegate = self;
//2.添加核心動(dòng)畫
[self.customView.layer addAnimation:keyAnima forKey:nil];
//beginTime:可以用來設(shè)置動(dòng)畫延遲執(zhí)行時(shí)間印颤,若想延遲2s您机,就設(shè)置為CACurrentMediaTime()+2,CACurrentMediaTime()為圖層的當(dāng)前時(shí)間
}
-(void)animationDidStart:(CAAnimation *)anim{
NSLog(@"開始動(dòng)畫"); }
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
NSLog(@"結(jié)束動(dòng)畫"); }
1.5----
3年局、使用path际看,讓layer在指定的路徑上移動(dòng)(畫圓)
//1.創(chuàng)建核心動(dòng)畫
CAKeyframeAnimation *keyAnima=[CAKeyframeAnimation animation];
keyAnima.keyPath=@"position";//平移
//1.1告訴系統(tǒng)要執(zhí)行什么動(dòng)畫
//創(chuàng)建一條路徑
CGMutablePathRef path = CGPathCreateMutable();
//設(shè)置一個(gè)圓的路徑
CGPathAddEllipseInRect(path, NULL, CGRectMake(150, 100, 100, 100));
keyAnima.path = path; //可以通過path屬性,讓layer在指定的軌跡上運(yùn)動(dòng)矢否。
//有create就一定要有release
CGPathRelease(path);
//1.2...1.5 同上
//2.添加核心動(dòng)畫
[self.customView.layer addAnimation:keyAnima forKey:@"key"];
//3 動(dòng)畫停止
- (void)stopOnClick:(UIButton *)button {
//停止self.customView.layer上名稱標(biāo)示為key的動(dòng)畫
[self.customView.layer removeAnimationForKey:@"key"];
//[self.customView.layer removeAllAnimations];//移除全部動(dòng)畫
}
4仲闽、抖動(dòng)(旋轉(zhuǎn))
#define angle2Radian(angle)? ((angle)/180.0*M_PI)
//1.創(chuàng)建核心動(dòng)畫
CAKeyframeAnimation *keyAnima = [CAKeyframeAnimation animation];
keyAnima.keyPath = @"transform.rotation";//旋轉(zhuǎn)
//設(shè)置動(dòng)畫時(shí)間
keyAnima.duration = 0.1;
//設(shè)置圖標(biāo)抖動(dòng)弧度
//把度數(shù)轉(zhuǎn)換為弧度? 度數(shù)/180*M_PI
keyAnima.values = @[@(-angle2Radian(4)), @(angle2Radian(4)), @(-angle2Radian(4))];//向左向右偏轉(zhuǎn)一個(gè)弧度(4),產(chǎn)生抖動(dòng)的視覺效果
//設(shè)置動(dòng)畫的重復(fù)次數(shù)(設(shè)置為最大值)
keyAnima.repeatCount = MAXFLOAT;
keyAnima.fillMode = kCAFillModeForwards;
keyAnima.removedOnCompletion = NO;
//2.添加動(dòng)畫
[self.iconView.layer addAnimation:keyAnima forKey:nil];
四僵朗、轉(zhuǎn)場(chǎng)動(dòng)畫 CATransition
CAAnimation的子類赖欣,用于做轉(zhuǎn)場(chǎng)動(dòng)畫,能夠?yàn)閷犹峁┮瞥銎聊缓鸵迫肫聊坏膭?dòng)畫效果验庙。iOS比Mac OS X的轉(zhuǎn)場(chǎng)動(dòng)畫效果少一點(diǎn)
UINavigationController就是通過CATransition實(shí)現(xiàn)了將控制器的視圖推入屏幕的動(dòng)畫效果
屬性解析:
type:動(dòng)畫過渡類型
subtype:動(dòng)畫過渡方向
startProgress:動(dòng)畫起點(diǎn)(在整體動(dòng)畫的百分比)
endProgress:動(dòng)畫終點(diǎn)(在整體動(dòng)畫的百分比)
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]];
//創(chuàng)建核心動(dòng)畫
CATransition *ca=[CATransition animation];
//告訴要執(zhí)行什么動(dòng)畫
//設(shè)置過度效果
ca.type=@"cube";
//設(shè)置動(dòng)畫的過度方向(向左)
ca.subtype=kCATransitionFromLeft;
//設(shè)置動(dòng)畫的時(shí)間
ca.duration=2.0;
//添加動(dòng)畫
[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.創(chuàng)建核心動(dòng)畫
CATransition *ca=[CATransition animation];
//1.1告訴要執(zhí)行什么動(dòng)畫
//1.2設(shè)置過度效果
ca.type=@"cube";
//1.3設(shè)置動(dòng)畫的過度方向(向右)
ca.subtype=kCATransitionFromRight;
//1.4設(shè)置動(dòng)畫的時(shí)間
ca.duration=2.0;
//1.5設(shè)置動(dòng)畫的起點(diǎn)
ca.startProgress=0.5;
//1.6設(shè)置動(dòng)畫的終點(diǎn)
//? ? ca.endProgress=0.5;
//2.添加動(dòng)畫
[self.iconView.layer addAnimation:ca forKey:nil]; }
五粪薛、組動(dòng)畫 CAAnimationGroup
1悴了、簡(jiǎn)介
CAAnimation的子類,可以保存一組動(dòng)畫對(duì)象违寿,將CAAnimationGroup對(duì)象加入層后湃交,組中所有動(dòng)畫對(duì)象可以同時(shí)并發(fā)運(yùn)行
屬性解析:
animations:用來保存一組動(dòng)畫對(duì)象的NSArray
默認(rèn)情況下,一組動(dòng)畫對(duì)象是同時(shí)運(yùn)行的藤巢,也可以通過設(shè)置動(dòng)畫對(duì)象的beginTime屬性來更改動(dòng)畫的開始時(shí)間
2搞莺、代碼
// 平移動(dòng)畫
CABasicAnimation *a1 = [CABasicAnimation animation];
a1.keyPath = @"transform.translation.y";
a1.toValue = @(100);
// 縮放動(dòng)畫
CABasicAnimation *a2 = [CABasicAnimation animation];
a2.keyPath = @"transform.scale";
a2.toValue = @(0.0);
// 旋轉(zhuǎn)動(dòng)畫
CABasicAnimation *a3 = [CABasicAnimation animation];
a3.keyPath = @"transform.rotation";
a3.toValue = @(M_PI_2);
// 組動(dòng)畫
CAAnimationGroup *groupAnima = [CAAnimationGroup animation];
groupAnima.animations = @[a1, a2, a3];
//設(shè)置組動(dòng)畫的時(shí)間
groupAnima.duration = 2;
groupAnima.fillMode = kCAFillModeForwards;
groupAnima.removedOnCompletion = NO;
[self.iconView.layer addAnimation:groupAnima forKey:nil];