1.視圖動畫
UIView提供了豐富的動畫功能,最常見是animateWithDuration:animations: completion:了欺旧,我們先看下面這個簡單的例子:
- (void)viewDidLoad {
[super viewDidLoad];
self.circleView = [[CircleView alloc] initWithFrame:
CGRectMake(0, 0, 20, 20)];
self.circleView.center = CGPointMake(100, 40);
[[self view] addSubview:self.circleView];
self.squareView = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 100, 100)];
_squareView.backgroundColor = [UIColor blackColor];
[self.view addSubview:_squareView];
UITapGestureRecognizer *g = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dropAnimate:)];
[[self view] addGestureRecognizer:g];
}
- (void)dropAnimate:(UIGestureRecognizer *)recognizer {
[UIView animateWithDuration:3 animations:^{
recognizer.enabled = NO;
self.circleView.center = CGPointMake(100, 300);
CGRect newFrame = CGRectMake(self.squareView.frame.origin.x + 150,
self.squareView.frame.origin.y,
self.squareView.frame.size.width,
self.squareView.frame.size.height);
self.squareView.frame = newFrame;
self.squareView.alpha = 0.5;
}
completion:^(BOOL finished){
[UIView animateWithDuration:1 animations:^{
self.circleView.center = CGPointMake(250, 300);
}
completion:^(BOOL finished){
recognizer.enabled = YES;
}
];
}];
}
這是一種基于視圖的最簡單的動畫了栅哀,常用于大小称龙、位置、不透明度的變換痴柔,運行結(jié)果如下:
上面的例子中马昨,我們只要在animations中寫入我們需要進行動畫效果的view的結(jié)束狀態(tài),然后在animateWithDuration中給出動畫時間,改方法就會自動完成動畫效果疙渣。
此外,我們還使用了recognizer.enabled = NO來禁止動畫過程中的手勢觸摸泼菌,防止動畫過程中你再次觸摸后又會重新開始動畫效果。
為了讓動畫看起來更酷哗伯,你需要使用Core Animation.Core Animation中最基礎也是最重要的部分就是CALayer焊刹。
2.CALayer
在iOS中,你能看得見摸得著的東西基本上都是UIView俩滥,比如一個按鈕贺奠、一個文本標簽、一個文本輸入框挂据、一個圖標等等儿普,這些都是UIView。UIView之所以能顯示在屏幕上婚脱,完全是因為它內(nèi)部的一個圖層勺像,即CALayer。
換句話說篮洁,UIView本身不具備顯示的功能,擁有顯示功能的是它內(nèi)部的圖層袁波。,CALayer和UIView很多方面都很像蜗侈,它也有位置、大小枷颊、變形和內(nèi)容,和UIView不同在于它不能處理事件(如觸摸事件)信卡,它完全屬于繪制那方面的內(nèi)容题造。所以UIView使用CALayer來管理繪制內(nèi)容,這樣兩者就可以協(xié)調(diào)得很好丢习。
使用之前首先記得引用:#import <QuartzCore/QuartzCore.h>.
CALayer 能夠?qū)?UIView 做許多設定仔蝌,如:陰影、邊框渊鞋、圓角和透明效果等瞧挤,且這些設定都是很有用的
1.borderWidth 和 boarderColor : 邊框顏色和寬度;
2contents:顯示的圖片內(nèi)容:CDImage
3.cornerRadius : UIView 的圓角执俩;
4masksToBounds :設為true切去超過邊界的子視圖,和UIView的clipsToBounds類似癌刽;
4shadowColor: 設置shadow的顏色
5.shadowPath : 設置shadow的位置
6.shadowOffset :設置陰影的偏移量,如果為正數(shù)衡奥,則代表為往右邊偏移
7.shadowOpacity :設置陰影的透明度(0~1之間远荠,0表示完全透明)
8.shadowRadius : shadow的漸變距離,從外圍開始档址,往里漸變shadowRadius距離
9.bounds : UIView 的大辛诎稹;
10.opacity : UIView 的透明效果含友;
a.設置view的layer屬性
我們在storyBoard中拖入一個120*120的UIView并連接至IBOutler:
設置UIView 的邊框顏色和寬度和圓角校辩,注意,設置UIView的圓角,若為UIView是正方形宜咒,cornerRadius是邊長的一半的話,則顯示為圓形儿咱。
self.CALayoutView.layer.borderWidth=5;
self.CALayoutView.layer.borderColor=[UIColor purpleColor].CGColor;
self.CALayoutView.layer.cornerRadius=60;
如下:
在view的圖層上添加一個image并設置陰影效果:
self.CALayoutView.layer.contents=(id)[UIImage imageNamed:@"photo"].CGImage;
self.CALayoutView.layer.shadowColor=[UIColor blackColor].CGColor;
self.CALayoutView.layer.shadowOffset=CGSizeMake(15, 5);
self.CALayoutView.layer.shadowOpacity=0.6;
self.CALayoutView.layer.shadowRadius = 1;
裁剪視圖:
self.CALayoutView.layer.masksToBounds = YES;
不過這樣陰影效果也裁去了:
b.子類化CALayer
你可以通過子類化CALayer并覆蓋以下方法:
[CALayer display]
[CALayer drawInContext:]
覆蓋圖層的display方法可直接設置圖層的contents屬性混埠。
覆蓋圖層的drawInContext:方法可以將需要的內(nèi)容繪制到提供的圖形上下文中钳宪。
選擇何種方法依賴于在繪圖過程中你需要多少的控制扳炬。display方法是更新圖層內(nèi)容的主要入口點,所以覆蓋這個方法讓你處于完全的過程控制中半醉。覆蓋display方法也意味你需要負責contents屬性創(chuàng)建CGImageRef對象劝术。如果你只是想繪制內(nèi)容(或讓你的圖層管理繪圖操作),你可以覆蓋drawInContext:方法并讓圖層為你創(chuàng)建內(nèi)容儲備衬吆。
如下:
MyLayer.m
@implementation MyLayer
-(void)display{
self.bounds=CGRectMake(50, 50, 50, 50);
self.position=CGPointMake(50, 50);
self.contents=(id)[UIImage imageNamed:@"photo"].CGImage;
self.cornerRadius=5;
self.masksToBounds=YES;
self.borderWidth=3;
self.borderColor=[UIColor brownColor].CGColor;
}
然后在view的layer圖層添加subLayer
CALayer *myLayer = [MyLayer layer];
[myLayer setNeedsDisplay];
[self.view.layer addSublayer:myLayer];
效果:
c.使用代理提供圖層的內(nèi)容
或者使用代理對象(即UIView或ViewController作為代理對象)實現(xiàn)以下方法
[delegate displayLayer:]
[delegate drawLayer:inContext:]
如果你的代理實現(xiàn)了displayLayer:方法咆槽,實現(xiàn)方法負責創(chuàng)建位圖并賦值給contents屬性圈纺。一般實現(xiàn)該方法是因為位圖有多種狀態(tài)并且都有各自的狀態(tài),按鈕就是這樣子的灯谣。
如果你沒有預渲染的圖片或者輔助對象來創(chuàng)建位圖蛔琅。代理對象可以使用drawLayer:inContext:方法,Core Animation創(chuàng)建一個位圖辜窑,創(chuàng)建一個用于繪制位圖的上下文,并調(diào)用代理方法填充該位圖穆碎。你的代理方法所要做的是將內(nèi)容畫在圖形上下文上。一般可以使用Core Graphics來繪制方面,不過使用UIGraphicsPushContext方法的話色徘,也可以通過UIKit做到。
代理對象必須實現(xiàn)displayLayer:或者drawLayer:inContext方法之一横腿。如果代理對象把這兩個方法都實現(xiàn)了辙培,圖層只調(diào)用displayLayer:方法。
不過有一個需要注意的問題搀别,在自定義view中(子類化CALayer也是)上述方法不會自己調(diào)用尾抑,只能自己通過setNeedDisplay方法標記CALayer需要重繪,這樣就可以自動繪制所有子視圖了榜苫。UIView默認在你需要它的時候繪制翎冲,而CALayer則在你明確要求它時才會繪制。
[self.layer setNeedsDisplay];
我們來舉一個例子驹饺,在drawLayer:inContext中通過UIKit進行繪制缴渊。(使用Core Graphics的方法可以見上一篇文章)
DelegateView.m
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self.layer setNeedsDisplay];
}
return self;
}
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
UIGraphicsPushContext(ctx);
[[UIColor lightGrayColor] set];
UIRectFill(layer.bounds);
UIFont *font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];
UIColor *color = [UIColor blackColor];
NSMutableParagraphStyle *style = [NSMutableParagraphStyle new];
[style setAlignment:NSTextAlignmentCenter];
NSDictionary *attribs = @{NSFontAttributeName: font,
NSForegroundColorAttributeName: color,
NSParagraphStyleAttributeName: style};
NSAttributedString *
text = [[NSAttributedString alloc] initWithString:@"孫悟空"
attributes:attribs];
[text drawInRect:CGRectInset([layer bounds], 10, 10)];
UIGraphicsPopContext();
}
CALayoutViewController.m
UIView *delegateView = [[DelegateView alloc] initWithFrame:CGRectMake(120, 400, 120, 50)];
delegateView.center = self.view.center;
[self.view addSubview:delegateView];
注意上面衔沼,我們不需要把UIView設置為CALayer的delegate昔瞧,因為UIView對象已經(jīng)是它內(nèi)部根層的delegate自晰,再次設置為其他層的delegate就會出問題擎鸠。如果你是在控制器中實現(xiàn)CALayer的delegate方法缘圈,你就需要指定:
layer.delegate=self
效果:
當UIView需要在屏幕顯示時糟把,它內(nèi)部會準備好一個CGContextRef(圖形上下文),然后調(diào)用delegate的drawLayer:inContext:方法遣疯,并且傳入已經(jīng)準備好的CGContextRef對象。
而UIView在drawLayer:inContext:方法中又會調(diào)用自己的drawRect:方法数苫。平時在drawRect:中通過UIGraphicsGetCurrentContext()獲取的就是以上傳入的CGContextRef對象辨液,在drawRect:中完成的所有繪圖都會填入層的CGContextRef中,然后被拷貝至屏幕止吁。
3.開始動畫
先看一張類的繼承結(jié)構(gòu)圖:
CAAnimation是所有動畫類的父類敬惦,但是它不能直接使用,應該使用它的子類俄删。能用的動畫類只有4個子類:CABasicAnimation奏路、CAKeyframeAnimation、CATransition迅矛、CAAnimationGroup潜叛。CAMediaTiming是一個協(xié)議(protocol)壶硅。
CAPropertyAnimation是CAAnimation的子類庐椒,但是不能直接使用蚂踊,要想創(chuàng)建動畫對象,應該使用它的兩個子類:CABasicAnimation和CAKeyframeAnimation棱诱。
它有個NSString類型的keyPath屬性涝动,你可以指定CALayer的某個屬性名為keyPath,并且對CALayer的這個屬性的值進行修改靡菇,達到相應的動畫效果厦凤。比如育苟,指定@"position"為keyPath,就會修改CALayer的position屬性的值笨腥,以達到平移的動畫效果
1).隱式動畫
上一篇文章我們講了如何在圖層中繪圖勇垛,現(xiàn)在需要開始使用圖層來創(chuàng)建動畫了。如下所示谆级,我們對MyLayer添加以兩秒到達終點的移動效果讼积。
- (void)viewDidLoad {
...省略
[self.view addGestureRecognizer: [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(drop:)]];
}
- (void)drop:(UIGestureRecognizer *)recognizer {
[CATransaction setAnimationDuration:1.0];
NSArray *layers = self.view.layer.sublayers;
NSLog(@"--%@",layers);
//由打印出來的數(shù)組得知第5個是MyLayer
CALayer *layer = [layers objectAtIndex:4];
CGPoint toPoint = CGPointMake(160, 210);
[layer setContents:(id)[UIImage imageNamed:@"id"].CGImage];
[layer setPosition:toPoint];
[layer setBounds:CGRectMake(0, 0, 90, 90)];
}
每一個UIView內(nèi)部都默認關聯(lián)著一個CALayer勤众,我們可用稱這個Layer為Root Layer(根層),所有的非Root Layer们颜,也就是手動創(chuàng)建的CALayer對象(比如上面例子中的MyLayer)吕朵,都存在著隱式動畫猎醇。
什么是隱式動畫?
當對非Root Layer的部分屬性進行修改時努溃,默認會自動產(chǎn)生一些動畫效果,這些屬性稱為Animatable Properties(可動畫屬性)
幾乎所有的層的屬性都是隱性可動畫的硫嘶,你可以查找文檔中那些屬性是可動畫屬性:
例如上面那個例子的運行效果如下:
2).顯式動畫
隱式動畫大部分情況下可以達到你的要求,不過有時候你需要更多的控制梧税,這就需要用到CAAnimation了沦疾。隱式動畫就是通過CAAnimation來實現(xiàn)的哮塞,因此所有可以在隱式動畫完成的事情在顯式動畫中都可以做到彻桃。
下面是最基本的動畫CABasicAnimation的例子:
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"opacity"];
anim.fromValue = @1.0;
anim.toValue = @0.0;
anim.autoreverses = YES;
anim.repeatCount = INFINITY;
anim.duration = 2.0;
[layer addAnimation:anim forKey:@"anim"];
效果如下:它會每隔兩秒重復繪制一次圖層,將不透明度從1改為0剔交。
你可以通過以下方法移除這個動畫來停止它:
[layer removeAnimationForKey:@"anim"];
動畫有它的(key)關鍵幀岖常、(fromValue)起始值葫督、(toValue)目標值橄镜、(timingFunction)時間函數(shù)洽胶、(duration)持續(xù)時間等。它的工作原理是創(chuàng)建圖層的多個副本丐怯,然后把它們顯示出來读跷。我們再看另外一個動畫:
CABasicAnimation *animation = [CABasicAnimation animation];
animation.keyPath = @"position.x";
animation.byValue = @120;
animation.duration = 2;
animation.beginTime = CACurrentMediaTime()+1.5;
[layer addAnimation:animation forKey:@"positionX"];
注意動畫的鍵路徑效览,也就是 position.x,實際上包含一個存儲在 position 屬性中的 CGPoint 結(jié)構(gòu)體成員订雾。這是 Core Animation 一個非常方便的特性嘿期。另外我們可以用byValue替代fromValue和toValue,只需要指定它的變化值伯顶,不需要指定它的起始值和目標值秀睛。
關于beginTime下一小節(jié)會講到抽兆。
效果如下:
有一個問題辫红,那就是動畫結(jié)束后圖層會很快地回到原點贴妻,我們把這種現(xiàn)象叫作jump back(閃回),要解決這個問題你需要了解model layer(模型層)和presentation layer(表示層)的概念和區(qū)別澎胡。
模型層是由開始動畫前的CALayer對象的屬性定義的攻谁。當開始動畫后戚宦,CAAnimation創(chuàng)建了CALayer對象的副本并進行修改阁苞,使其變成表現(xiàn)層祠挫,你可以大致理解為就是它們在屏幕上顯示什么內(nèi)容等舔。
前面的示例中,當執(zhí)行動畫時甚牲,狀態(tài)從模型層變?yōu)楸憩F(xiàn)層丈钙,表現(xiàn)層被繪制到屏幕上,繪制完成后劫笙,所有的更改都會丟失并由模型層決定當前狀態(tài)填大,因為模型層沒有改變俏橘,所以會恢復到一開始的狀態(tài)寥掐。
解決方法1:你可以通過設置動畫的 fillMode 屬性為 kCAFillModeForwards或kCAFillModeBoth使得動畫 以留在最終狀態(tài)曹仗,并設置removedOnCompletion 為 NO 以防止它被自動移除:
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;
但這不是好的解決方法怎茫,因為這樣模型層永遠不會更新轨蛤,如果之后對它進行隱性動畫祥山,那它不會正常工作缝呕。
解決方法2:直接在 model layer 上更新屬性
我們先移除上面的隱式動畫(待會會講到為什么)供常,然后
CABasicAnimation *animation = [CABasicAnimation animation];
animation.keyPath = @"position.x";
animation.fromValue = @50;
animation.toValue = @170;
//animation.byValue = @120;
animation.duration = 2;
animation.beginTime = CACurrentMediaTime()+1.2;
[layer addAnimation:animation forKey:@"positionX"];
layer.position = CGPointMake(170, 50);
注意這種情況下栈暇,我們必須指定fromValue和toValue源祈,不能使用byValue,我們最后指定了模型層的layer.position = CGPointMake(170, 50)手销,看看效果怎樣
啊哦锋拖,你發(fā)現(xiàn)了沒姑隅,現(xiàn)在是開始前有一個閃回(摔桌>笞病)
不過我們可以加入下面這句痪蝇,使得它在動畫開始之前不做任何動作
animation.fillMode = kCAFillModeBackwards;
關于kCAFillModeBackward和kCAFillModeForward的概念可以看下面這張圖:
再說一下之前被我們移除的隱性動畫趁矾,其實我們真正需要移除的是下面這個
[layer setPosition:toPoint];
因為它和我們的顯性動畫有沖突给僵。所以最好的解決辦法是在執(zhí)行顯示動畫時關閉隱式動畫
[CATransaction begin];
[CATransaction setDisableActions:YES];
...省略
[CATransaction commit];
所以其實我們可以針對這種情況寫一個分類:
@implementation CALayer (CALayer_RNAnimation)
- (void)setValue:(id)value
forKeyPath:(NSString *)keyPath
duration:(CFTimeInterval)duration
delay:(CFTimeInterval)delay {
[CATransaction begin];
[CATransaction setDisableActions:YES];
[self setValue:value forKeyPath:keyPath];
CABasicAnimation *anim;
anim = [CABasicAnimation animationWithKeyPath:keyPath];
anim.duration = duration;
anim.beginTime = CACurrentMediaTime() + delay;
anim.fillMode = kCAFillModeBoth;
anim.fromValue = [[self presentationLayer] valueForKey:keyPath];
anim.toValue = value;
[self addAnimation:anim forKey:keyPath];
[CATransaction commit];
}
3).關于定時
Core Animation中的時間是相對的蔓同,一秒時間不一定就是一秒鐘斑粱,與坐標一樣脯爪,時間是可以縮放的痕慢。Core Animation遵守CAMediaTiming協(xié)議守屉,可以設置其speed屬性來縮放它的時間跨度。
你可能會需要在某個圖層的動畫結(jié)束后開始自己的動畫思灌,因此你需要對它們之間的時間進行轉(zhuǎn)換泰偿,就像轉(zhuǎn)換不同視圖中的點一樣耗跛。
CAAnimation *otherAnim = [layer animationForKey:@"anim"];
CFTimeInterval finish = otherAnim.beginTime + otherAnim.duration;
myAnim.beginTime = [self convertTime:finish fromLayer:layer];
如果想引用當前時間调塌,可以使用CACurrentMediaTime()惠猿,例如:
anim.beginTime = CACurrentMediaTime()+3.0;
anim.fillMode = kCAFillModeBackwards;
該動畫會在前3秒保存不動偶妖,3秒后開始動畫趾访。
你想要為你的動畫定義超過兩個步驟扼鞋,我們可以使用更通用的 CAKeyframeAnimation云头,而不是去鏈接多個 CABasicAnimation 實例盘寡。
4).CAKeyframeAnimation
跟CABasicAnimation的區(qū)別是:CABasicAnimation只能從一個數(shù)值(fromValue)變到另一個數(shù)值(toValue)竿痰,而CAKeyframeAnimation會使用一個NSArray保存這些數(shù)值
包含以下屬性:
values:就是上述的NSArray對象影涉。里面的元素稱為”關鍵幀”(keyframe)蟹倾。動畫對象會在指定的時間(duration)內(nèi)肌厨,依次顯示values數(shù)組中的每一個關鍵幀
path:可以設置一個CGPathRef\CGMutablePathRef,讓層跟著路徑移動柑爸。path只對CALayer的anchorPoint和position起作用表鳍。如果你設置了path譬圣,那么values將被忽略
keyTimes:可以為對應的關鍵幀指定對應的時間點,其取值范圍為0到1.0,keyTimes中的每一個時間值都對應values中的每一幀.當keyTimes沒有設置的時候,各個關鍵幀的時間是平分的
CABasicAnimation可看做是最多只有2個關鍵幀的CAKeyframeAnimation
a).多步動畫
下面的例子我們值改變values的值厘熟,即定義關鍵幀盯漂。關鍵幀(keyframe)使我們能夠定義動畫中任意的一個點就缆,然后讓 Core Animation 填充所謂的中間幀竭宰。先看運行效果:
代碼如下:
- (IBAction)enter:(id)sender {
if (![self.textField.text isEqualToString:@"123456"]) {
[self lockAnimationForView:self.textField];
}
}
-(void)lockAnimationForView:(UIView*)view
{
CALayer *layer = [view layer];
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"position.x";
animation.values = @[ @0, @5, @10, @-10, @10, @5, @0 ];
animation.keyTimes = @[ @0, @(1 / 6.0),@(2 / 6.0), @(3 / 6.0), @(5 / 6.0),@(2 / 6.0), @1 ];
animation.duration = 0.4;
animation.additive = YES;
[layer addAnimation:animation forKey:@"shake"];
}
values 數(shù)組定義了UITextField應該到哪些位置切揭。設置 keyTimes 屬性讓我們能夠指定關鍵幀動畫發(fā)生的時間廓旬。它們被指定為關鍵幀動畫總持續(xù)時間的一個分數(shù)孕豹。
設置 additive 屬性為 YES 使 Core Animation 在更新表現(xiàn)層之前將動畫的值添加到模型層中去励背。這使我們能夠?qū)λ行问降男枰碌脑刂赜孟嗤膭赢嬕睹迹覠o需提前知道它們的位置。因為這個屬性從 CAPropertyAnimation 繼承莲趣,所以你也可以在使用 CABasicAnimation 時使用它妖爷。
b).沿路徑的動畫
CAKeyframeAnimation 提供了更加便利的 path 屬性使得view可以沿著復雜路徑的動畫運動絮识。
舉個例子次舌,我們?nèi)绾巫屢粋€ view 做圓周運動:
代碼如下:
-(void)pathAnimation:(UITapGestureRecognizer*)tap{
tap.enabled = NO;
CALayer *layer = [self.pathView layer];
CGRect boundingRect = CGRectMake(-150, -150, 300, 300);
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"position";
animation.path = CFAutorelease(CGPathCreateWithEllipseInRect(boundingRect, NULL));
animation.duration = 4;
animation.additive = YES;
animation.repeatCount = HUGE_VALF;
animation.calculationMode = kCAAnimationPaced;
animation.rotationMode = kCAAnimationRotateAuto;
[layer addAnimation:animation forKey:@"path"];
}
我們使用 CGPathCreateWithEllipseInRect()創(chuàng)建一個圓形的 CGPath 作為我們的關鍵幀動畫的 path。
使用 calculationMode 是控制關鍵幀動畫時間的另一種方法逐沙。我們通過將其設置為 kCAAnimationPaced吩案,讓 Core Animation 向被驅(qū)動的對象施加一個恒定速度徘郭,不管路徑的各個線段有多長丧肴。將其設置為 kCAAnimationPaced 將無視所有我們已經(jīng)設置的 keyTimes芋浮。設置 rotationMode 屬性為 kCAAnimationRotateAuto 確保view沿著路徑旋轉(zhuǎn)纸巷。
5).時間函數(shù)
你會發(fā)現(xiàn)我們上面有些動畫有一些看起來不是很不自然何暇。那是因為我們在現(xiàn)實世界中看到的大部分運動需要時間來加速或減速裆站。為了給我們的動畫一個存在慣性的感覺羽嫡,我們可以通過引入一個 時間函數(shù) (timing function) (有時也被稱為 easing 函數(shù))來實現(xiàn)這個目標杭棵。該函數(shù)通過修改持續(xù)時間的分數(shù)來控制動畫的速度魂爪。
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
還包含:kCAMediaTimingFunctionEaseIn, kCAMediaTimingFunctionEaseOut, kCAMediaTimingFunctionEaseInEaseOut滓侍,你們可以自己試試效果如何撩笆。
你還可以參見類似這種小型庫 RBBAnimation缸浦,它包含一個允許使用 更多復雜 easing 函數(shù) 的自定義子類 CAKeyframeAnimation裂逐,包括反彈和包含負分量的 cubic Bézier 函數(shù)絮姆。
6).動畫組
對于某些復雜的效果篙悯,可能需要同時為多個屬性進行動畫鸽照。CAAnimationGroup可以保存一組動畫對象,將CAAnimationGroup對象加入層后定血,組中所有動畫對象可以同時并發(fā)運行澜沟。
默認情況下茫虽,一組動畫對象是同時運行的濒析,也可以單獨通過設置動畫對象的beginTime屬性來更改動畫的開始時間,示例如下:
-(void)groupAnimation:(UITapGestureRecognizer*)tap{
// 平移動畫
CABasicAnimation *animation1 = [CABasicAnimation animation];
animation1.keyPath = @"transform.translation.y";
animation1.toValue = @(100);
// 縮放動畫
CABasicAnimation *animation2 = [CABasicAnimation animation];
animation2.keyPath = @"transform.scale";
animation2.toValue = @(0.0);
// 旋轉(zhuǎn)動畫
CABasicAnimation *animation3 = [CABasicAnimation animation];
animation3.keyPath = @"transform.rotation";
animation3.toValue = @(M_PI_2);
// 組動畫
CAAnimationGroup *groupAnima = [CAAnimationGroup animation];
groupAnima.animations = @[animation1, animation2, animation3];
//設置組動畫的時間
groupAnima.duration = 2;
groupAnima.fillMode = kCAFillModeForwards;
groupAnima.removedOnCompletion = NO;
[self.groupViewFirst.layer addAnimation:groupAnima forKey:@"group"];
}
運行效果:
你可以在這里下載完整的代碼。如果你覺得對你有幫助主经,希望你不吝嗇你的star:)