CoreAnimation是一組非常強(qiáng)大 的API症昏,它可以做出來非常絢麗的動(dòng)畫效果卵蛉,前邊介紹了 CoreAnimation 的核心組件CALayer麸拄;
CAAnimation簡(jiǎn)介:是所有動(dòng)畫對(duì)象的父類氛悬,負(fù)責(zé)控制動(dòng)畫的持續(xù)時(shí)間和速度,是個(gè)抽象類粗悯,不能直接使用虚循,應(yīng)該使用它具體的子類;
常用的屬性:
屬性說明:(紅色代表來自CAMediaTiming協(xié)議的屬性)
duration:動(dòng)畫的持續(xù)時(shí)間
repeatCount:重復(fù)次數(shù),無限循環(huán)可以設(shè)置HUGE_VALF或者M(jìn)AXFLOAT
repeatDuration:重復(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)畫代理
話不多說莫杈,上代碼:
// 1. 初始化動(dòng)畫對(duì)象? 基本動(dòng)畫
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"];
// 設(shè)置代理
anim.delegate = self;
// 2. 設(shè)置動(dòng)畫屬性
[anim setToValue:[NSValue valueWithCGPoint:toValue]];
[anim setDuration:1.0f];
// 4. 添加動(dòng)畫到圖層
[self.myView.layer addAnimation:anim forKey:nil];
點(diǎn)擊屏幕,動(dòng)畫執(zhí)行完成奢入,后又返回初始位置筝闹,怎么能讓動(dòng)畫停留在最后點(diǎn)擊位置呢? 這時(shí)候 ? ? fillMode ? ?跟 removedOnCompletion ?就派上用場(chǎng)了;
anim.fillMode = kCAFillModeForwards; //逐漸逼近目標(biāo)點(diǎn)
?anim.removedOnCompletion = NO;
fillMode屬性值(要想fillMode有效腥光,最好設(shè)置removedOnCompletion = NO)
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 在動(dòng)畫開始前艘儒,只需要將動(dòng)畫加入了一個(gè)layer,layer便立即進(jìn)入動(dòng)畫的初始狀態(tài)并等待動(dòng)畫開始夫偶。
kCAFillModeBoth 這個(gè)其實(shí)就是上面兩個(gè)的合成.動(dòng)畫加入后開始之前界睁,layer便處于動(dòng)畫初始狀態(tài),動(dòng)畫結(jié)束后layer保持動(dòng)畫最后的狀態(tài)
設(shè)置完之后兵拢,在運(yùn)行翻斟,發(fā)現(xiàn)myView可以停留在手指點(diǎn)擊后的位置了。? 但是 很奇怪说铃,? view的Frame沒有任何變化? 访惜,可以用
?NSLog(@"%@",NSStringFromCGRect(self.myView.frame)); ?
在動(dòng)畫結(jié)束后,打印view的Frame觀察
想要解決這個(gè)問題腻扇,可以使用setValue:forKey:傳值
[anim setValue:[NSValue valueWithCGPoint:toValue] forKey:@"targetPoint1"];
[anim setValue:@"translationTo" forKey:@"animationType"];
然后在- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag 中設(shè)置 value的cener屬性债热,修改坐標(biāo)。
CGPoint targetPoint = [[anim valueForKey:@"targetPoint1"] CGPointValue];
NSLog(@"tragetPoint:%@",NSStringFromCGPoint(targetPoint));
完之后幼苛,在觀察view的frame窒篱, ?完美解決;
起始UIView幫我們封裝了CoreAnimation的基本動(dòng)畫, 使用起來也非常容易:
[UIView animateWithDuration:1.0f animations:^{
self.myView.center = location;
} completion:^(BOOL finished) {
NSLog(@"%@",NSStringFromCGRect(self.myView.frame));
}];
但是墙杯,只是封裝了一些基本動(dòng)畫配并,? 如果我們要實(shí)現(xiàn)比較復(fù)雜的動(dòng)畫(CAAnimationGroup),還是需要實(shí)現(xiàn)上面一坨代碼高镐。
縮放動(dòng)畫示例:
- (void)scaleAnim{
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
anim.toValue = @0.5;
anim.duration = 0.5;
anim.autoreverses = YES;? //自動(dòng)翻轉(zhuǎn)
[self.myView.layer addAnimation:anim forKey:nil];
}
旋轉(zhuǎn)動(dòng)畫:
- (void)rotationAnim{
self.myView.layer.anchorPoint = CGPointMake(0.8, 0.8);
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
//不停地旋轉(zhuǎn)
anim.toValue = @(2 * M_PI);
anim.repeatCount = HUGE_VALF;
anim.duration = 0.5;
//對(duì)于循環(huán)播放的動(dòng)畫效果溉旋,一定要removedOnCompletion設(shè)置為 No
anim.removedOnCompletion = NO;
[self.myView.layer? addAnimation:anim forKey:@"rotationAnim"];
}
暫停動(dòng)畫:
- (void)pauseAnim{
//1. 取出當(dāng)前的動(dòng)畫時(shí)間,要暫停的時(shí)間? CoreAnimation absolute time
CFTimeInterval currentTime = [self.myView.layer convertTime:CACurrentMediaTime() fromLayer:nil];
//2. 將動(dòng)畫的運(yùn)行速度設(shè)置 == 0? ? ==》動(dòng)畫默認(rèn)的運(yùn)行速度是 1.0 /速度的比例
self.myView.layer.timeOffset = currentTime;
//3. 設(shè)置動(dòng)畫的時(shí)間偏移量? ? =》 讓動(dòng)畫定格在該時(shí)間點(diǎn)
self.myView.layer.speed = 0.0f;
}
恢復(fù)動(dòng)畫:
- (void)continueAnim{
//1. 將動(dòng)畫的時(shí)間偏移量作為暫停時(shí)的時(shí)間點(diǎn)
CFTimeInterval pauseTime = self.myView.layer.timeOffset;
//2. 根據(jù)媒體時(shí)間計(jì)算出準(zhǔn)確的啟動(dòng)動(dòng)畫時(shí)間? ,? 對(duì)之前的暫停動(dòng)畫時(shí)間進(jìn)行修正
CFTimeInterval beginTime = CACurrentMediaTime() - pauseTime;
//3. 設(shè)置圖層的開始動(dòng)畫時(shí)間
self.myView.layer.beginTime = beginTime;
//4. 將timeOffset清空
self.myView.layer.timeOffset = 0.0f;
self.myView.layer.speed = 1.0f;
}
在appdelegate中獲取controller的方法:
ViewController *viewController =? (ViewController *)[application.windows.firstObject rootViewController];