標籤:style http color io os ar for strong sp
在iOS上實現動畫效果,基本都是在一段給定的時間內完成狀態的連續變化,包括背景色、Frame大小、位移、旋轉、透明度、縮放等。
老的動畫實現形式:
iOS 4.0之前,蘋果提供的是類似於資料庫中的事務編程的模式:
例如實現一個view的淡入效果,可以通過設定view的alpha實現(alpha = 1是全透明):
[UIView beginAnimations:nil context: nil]; [UIView setAnimationDuration:1.0]; //動畫的時間長度是1s [UIView setAnimationDelay:0.0]; //不延時執行 [UIView setAnimationDelegate:self]; [UIView setAnimationDidStopSelector:@selector(animationStopped)];//動畫完成後執行一些操作 self.view.alpha = 0.0;//最終的alpha為0,不透明 self.view.frame = CGRectMake(10, 10, 50, 50);//最終的frame [UIView commitAnimations];//提交動畫
實現了一個1s中的動畫,將view的透明度設為不透明,frame設為(10,10,50,50)。
用beginAnimations標識開始動畫,然後設定動畫的各種屬性,最後通過commitAnimations提交動畫,之後系統接管該動畫並執行。
Block動畫實現形式:
iOS4.0之後,蘋果提供了一組重載函數,實現了以block的形式執行動畫:
(void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations(void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion(void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion(void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion
比如下面這樣:
+ (void)fadeIn: (UIView *)view andAnimationDuration: (float) duration{ [view setAlpha:0.0]; NSLog(@"begin animation"); [UIView animateWithDuration:duration animations:^{ [view setAlpha:1.0]; NSLog(@"in animation block"); } completion:^(BOOL finished) { NSLog(@"completion animation"); }]; NSLog(@"exit fadeIn");}
通過參數duration、delay、options等分別設定動畫的時間、延時、執行選項。
在block animations中實現動畫的主體,在block completion中實現動畫完成後需要執行的邏輯。之所以有completion,是給我們一個在動畫跑完成後執行一些邏輯的入口(老的動畫方式通過setAnimationDidStopSelector實現)。
假如你想在動畫執行完成後做一些事情,那麼把代碼放在NSLog(@"in animation block")和NSLog(@"exit fadeIn")是有本質區別的。因為我們把動畫組裝好後就交給作業系統了,會立刻走到NSLog(@"exit fadeIn"),並不會阻塞主線程流程。
completion block會有一個BOOL型別參數,用來告知動畫是否真的執行完成了。這個參數的意義在於我們可以在completion中判斷之前的動畫是否真的執行完了,因為動畫是有可能被取消的(可以通過[view.layer removeAllAnimations]取消動畫),但無論是否取消,系統都會調用completion告知動畫執行結束(想象扔手雷的情境,在與地面發生碰撞時手雷飛行的動畫結束,接下來要執行爆炸的動畫,但如果手雷飛行時被人接住,那麼就需要取消飛行動畫,至於後面是否爆炸......)。甚至如果我們設定了動畫執行的時間duration是0時,completion也會被調用(雖然duration是0,但仍是非同步,系統會在下一個訊息迴圈的開始時立刻調用completion),此時BOOL參數仍然是YES。
前面說到提交動畫給系統後,動畫並不會阻塞主線程,但有時候我們希望在動畫結束前不要有其他邏輯進來,這可以通過在提交動畫後執行訊息迴圈輪詢變數狀態實現:
+ (void)fadeIn: (UIView *)view andAnimationDuration: (float) duration andWait:(BOOL) wait{ __block BOOL done = wait; //wait = YES wait to finish animation [view setAlpha:0.0]; [UIView animateWithDuration:duration animations:^{ [view setAlpha:1.0]; } completion:^(BOOL finished) { done = NO; }]; // wait for animation to finish while (done == YES) [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]];}
常見的動畫實現:
縮放--改變view.transform
view.transform = CGAffineTransformMakeScale(0, 0); [UIView animateWithDuration:duration animations:^{ view.transform = CGAffineTransformIdentity; } completion:^(BOOL finished) { }];
淡入淡出--改變view.alpha
[view setAlpha:0.0]; [UIView animateWithDuration:duration animations:^{ [view setAlpha:1.0]; } completion:^(BOOL finished) { }];
位置移動--改變view.center
[UIView animateWithDuration:duration animations:^{ view.center = CGPointMake(view.center.x - length, view.center.y); } completion:^(BOOL finished) { }];
旋轉--改變view.transform
[UIView animateWithDuration:duration animations:^{ view.transform = CGAffineTransformMakeRotation(degreesToRadians(angle)); } completion:^(BOOL finished) { }];
動畫嵌套:
在一個動畫執行完成後繼續執行動畫,甚至執行多個動畫形成動畫鏈:
這個帶回彈的氣泡彈齣動畫通過串列的3個改變view縮放值的動畫實現,在completion中繼續一個新的動畫。
self.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.001, 0.001); __unsafe_unretained NearbyGroupMapAnnotationView* reself = self; [UIView animateWithDuration:0.3/1.5 animations:^{ reself.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.1, 1.1); } completion:^(BOOL finished) { [UIView animateWithDuration:0.3/2 animations:^{ reself.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.9, 0.9); } completion:^(BOOL finished) { [UIView animateWithDuration:0.3/2 animations:^{ reself.transform = CGAffineTransformIdentity; }]; }]; }];
首先將view縮放到正常狀態的0.001倍作為初始態,
動畫1:開始將view放到到1.1倍
動畫2:將view縮小到0.9倍
動畫3:將view回複正常大小
減速動畫
(void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion
這個函數可以通過下面兩個很有意思的參數實作類別似彈簧的效果(帶加速度):
usingSpringWithDamping:(CGFloat)dampingRatioinitialSpringVelocity:(CGFloat)velocity
中有兩個動畫效果,一個是平穩的減速停止,一個是減速後帶有回彈(類似碰撞)。
usingSpringWithDamping標識了彈簧的強度,介於0~1之間。為1時,動畫將會平滑且沒有上下擺動的減速到他的最終狀態,當該值小於1時,動畫的擺動會越來越厲害。
initialSpringVelocity用來標識view開始收到彈簧作用力時的速度,介於0~1之間,假設整個動畫將移動100,當取1時,表示速度為100/1s。initialSpringVelocity越小速度越小。
其實,不用上面這個複雜的方法,通過串列多個相反方向的位移動畫,(分別控制他們的動畫時間類比加速度),也可以實現回彈的效果。
iOS動畫簡介