iOS 動畫

iOS中動畫分爲兩類,UIView動畫 和 CALayer動畫

UIView動畫可以給UIView的部分屬性添加動畫效果
支持動畫的屬性有:frame、center、bounds、alpha、transform、backgroundColor等;UIView動畫也支持翻轉或翻頁動畫效果:UIViewAnimationTransitionXXX;

UIView動畫和CALayer動畫比較:

  • UIView動畫本質上也是CALayer動畫;
  • 通過UIView動畫執行之後,UIView的相關屬性已經真實改變;而CALayer動畫默認在執行完畢後,會自動返回回去;並且執行完成後,即使設置動畫fillMode不變後,爲它設置的屬性也並不會改變;

下面來看一個UIView動畫實例

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:2.5];
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:view cache:YES];
    [UIView commitAnimations]; // 提交執行動畫

在第一個方法中,第一個參數是指定該動畫的名稱,第二個參數在動畫開始/結束的時候,會把這個參數給傳過來;兩個參數都可爲空。
除此之外還有其它方法:

+ (void)setAnimationDelegate:(nullable id)delegate;
// 設置代理
+ (void)setAnimationWillStartSelector:(nullable SEL)selector; 
// 單獨指定Start監聽 
+ (void)setAnimationDidStopSelector:(nullable SEL)selector; 
// 單獨指定Stop監聽  
+ (void)setAnimationCurve:(UIViewAnimationCurve)curve; 
// 設置漸變效果,默認是UIViewAnimationCurveEaseInOut
......

設置代理之後,實現UIViewController的以下兩個方法

-(void)animationWillStart:(NSString *)animationID context:(void *)context // 開始
-(void)animDidStoped:(id)sender finished:(NSNumber *)finished  context:(void *)context // 結束

上面是使用[UIView animation___]的形式,實現UIView動畫還可以通過Block的方式。

+ (void)animateWithDuration:(NSTimeInterval)duration
                      delay:(NSTimeInterval)delay
                    options:(UIViewAnimationOptions)options
                 animations:(void (^)(void))animations
                 completion:(void (^)(BOOL finished))completion

UIView只是一個矩形區域,真正負責顯示渲染的是CALayer;

CALayer
iOS中的層類,是圖形界面的基礎,所有的界面元素都源自於它;
UIView中有一個readonly的屬性就是layer;CALayer同樣也有frame,bounds,backgroundColor等屬性;如果一個控件是另一個控件的子控件,那麼這個控件中的layer也是另外一個控件的子layer

可以通過UIView的layer屬性,給視圖添加陰影,邊框等效果;

shadowOffset  // 陰影偏移量
shadowColor  // 陰影顏色
shadowOpacity  // 陰影透明度,默認爲0
borderWidth  // 邊框寬度
borderColor  // 邊框顏色

CALayer特有的兩個屬性

anchorPoint // 錨點,默認是在視圖的中心,值爲(0.5,0.5),左上角爲(1,1); 
position  // position是錨點基於父視圖原點的位置;

修改position,錨點不變,但frame會變化;
修改錨點,position不變,但frame會變化;

view.layer.borderWidth = 10;
view.layer.borderColor = [UIColor greenColor].CGColor;
view.layer.cornerRadius = 10;  // 圓角
view.layer.masksToBounds = YES; // 超出主圖層的部分剪切掉;
view.clipsToBounds = YES;
view.layer.bounds = CGRectMake(0, 0, 100, 100);
view.layer.position = CGPointMake(100, 100);
// 設置的image不是展示在主圖層上的,而是展示在子圖層上的;
view.layer.contents = (id)[UIImage imageName:@"xxx"].CGImage;
view.layer.shadowColor;  // 陰影顏色
view.layer.shadowOffset = CGSizeMake(-10 ,0);  // 設置陰影偏移
view.layer.shadowOpacity;  // 陰影透明度,1:完全不透明

CALayer動畫3種實現形式

view.layer.transform = CATransform3DMakeTranslation(0, 0, 100);
NSValue *v = [NSValue valueWithCATransform3D:CATransform3DMakeTranslation(0,-100,0)];
[view.layer setValue:v forKeyPath:@"transform"];
[view.layer setValue:@(100) forKeyPath:@"transform.translation.x"];

自定義CALayer
1.重寫drawInContext方法,在此方法中給layer繪製圖形,注意CALayer中的drawInContext方法,不會自動調用,只能通過setNeedsDisplay方法調用;

-(void)drawInContext:(ContextRef)ctx

2.另一個使用CALayer渲染的方法

layer.delegate = self; 
// 在self這個對象中重寫
drawLayer:(CALayer *)layer inContext:(ContextRef)ctx // 在該方法中進行渲染;

每個UIView內部都默認關聯一個CALayer,這個Layer稱爲RootLayer,所有的非rootLayer,也就是手動創建的CALayer,都存在隱式動畫,也就是當對這些非rootLayer的部分屬性進行修改時,默認會自動附帶動畫效果;在UIView的頭文件中,包含Animatable的屬性都支持隱式動畫;
<1>.關閉隱式動畫

[CATransaction begin];
[CATransaction setDisableActions:YES];
[layer.bounds = CGRectMake(0, 0, 100, 100);  // 隱式動畫;
[CATransaction commit];

CAAnimation
CAAnimation類中封裝了iOS中所有的動畫效果,動畫是添加在Layer上的,(CoreAnimation是直接作用在CALayer上)是動畫的觸發核心,常見的有透明,飄浮,縮放;
CAAnimation類是抽象父類,它有三個子類:

CAPropertyAnimation
 - CABasicAnimation 
 - CAKeyFrameAnimation
CAAnimationGroup
CATransition

其中CAPropertyAnimation又有兩個子類,用來給CALayer的部分屬性添加動畫;

1.CABasicAnimation

keyPath;
fromValue;
toValue;
byValue;

keyPath就是CALayer中可以做動畫的屬性,比如position,對於position屬性,它是一個結構體,這時候我們還可以繼續指定keyPath爲position.x;調用構造方法animationWithKeyPath:@”position.x”;與此同時,fromValue和toValue也要改爲對應的keyPath對應的類型;

Example

CABasicAnimation *anim = [CABasicAnimation animation];
anim.keyPath = @"position";  // 設置需要發生動畫的屬性
anim.keyPath = @"bounds";  // toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, 200, 200)];
anim.keyPath = @"transform";  // toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(PI, 0, 0, 1)];
anim.keyPath = @"transform.translation.y";  // toValue = @(100);
anim.fromValue;
anim.toValue;
anim.removedOnCompletion = NO;  // 設置動畫執行完畢後不刪除動畫;
anim.fillMode = kCAFillModeForwards;  // 設置保存動畫的最新狀態;
[layer addAnimation:anim forKey:nils];  // 添加核心動畫到layer;

2.CAKeyFrameAnimation
關鍵幀動畫,某一屬性按照一串數值來執行動畫

anim.keyPath; // 同上
anim.values;
anim.keyTimes;  // 用於設置每一幀動畫結束的時候佔用總時長百分比;
anim.repeatCount;  // 重複次數;
anim.timimgFunction = [CAMediaTimingFunction functionWithName:...]; // 動畫速率
anim.path;  // 幀動畫還可以指定一個路徑,讓layer沿指定路徑運動;路徑對象爲一個CGMutablePathRef對象實例(路徑指定後需要手動release該路徑);
delegate;  
// 動畫代理,指定爲一個NSObject對象,NSObject對象中有兩個方法animationDidStart 和animationDidStop,分別表示動畫開始和動畫結束;
[layer removeAnimationForKey:(NSString *)]; // 停止動畫

Example

    CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    NSArray *arr = [NSArray arrayWithObjects:[NSValue valueWithCGPoint:CGPointMake(100, 100)],
                    [NSValue valueWithCGPoint:CGPointMake(20, 20)],
                    [NSValue valueWithCGPoint:CGPointMake(200, 150)],
                    [NSValue valueWithCGPoint:CGPointMake(140, 210)],
                    [NSValue valueWithCGPoint:CGPointMake(200, 150)], nil];
    anim.values = arr;
    anim.keyTimes = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.1],
                     [NSNumber numberWithFloat:0.3],
                     [NSNumber numberWithFloat:0.4],
                     [NSNumber numberWithFloat:0.7],
                     [NSNumber numberWithFloat:1.0], nil];
    anim.duration = 2;
    [self.uiview.layer addAnimation:anim forKey:@""];

3.CATransition
主要用於提供一些過渡效果;
改變一個view的位置,角度等可以通過設置view.transform來實現;

CGAffineTransformMakeRotation
CGAffineTransformMakeScale
CGAffineTransformMakeTranslation

CGAffineTransformXXX:2D仿射變換,不屬於動畫,但是經常和動畫配合使用,view上的每個點按照一定規律變化,可做出縮放,旋轉,平移等效果;

[UIView beginAnimations:@"a" context:NULL];
[UIView setAnimationDuration:2];
self.uiview.transform = CGAffineTransformMakeScale(1.2, 1.7);
// self.uiview.transform = CGAffineTransformRotate(self.uiview.transform, M_PI / 4);
[UIView commitAnimations];
CATransition *anim = [CATransition animation];
anim.duration = 1.0;
anim.type = @"pageCurl";  // 動畫過渡類型 | cube | kCATransitionMoveIn
anim.subtype = kCATransitionFromRight;  // 動畫過渡方向
anim.delegate =; // 代理
[view.layer addAnimation:aim forKey:nil];

UIView執行Transition(轉場)動畫

[UIView transitionWithView:view duration:2.0 options:UIViewAnimationOptionsTransitionFlipFromLeft animations:^{
    view.image = [UIImage imageNamed:@""]; 
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];
} completion:^(BOOL finished){
}]; // 旋轉的同時切換圖片

3D動畫

view.layer.transform = CATransform3DMakeRotation(M_PI_2, 0, 1, 0); // 讓view繞y軸旋轉90度

4.CAAnimationGroup

    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
    anim.fromValue = (id)[UIColor redColor].CGColor;
    anim.toValue = (id)[UIColor blueColor].CGColor;
    anim.duration = 2;

    CABasicAnimation *anim1 = [CABasicAnimation animationWithKeyPath:@"position.x"];
    anim1.fromValue = (id)[NSNumber numberWithInt:100];
    anim1.toValue = (id)[NSNumber numberWithInt:200];
    anim1.duration = 2;

    CAAnimationGroup * group = [CAAnimationGroup animation];
    NSArray *arr = [NSArray arrayWithObjects:anim  ,anim1 , nil];
    group.animations = arr;
    group.duration = 3;
    [self.uiview.layer addAnimation:group forKey:@""];

Transform:動畫需要回到原始狀態的時候使用該動畫;

[UIView animationWithDuration:duration animations:^{
} completion:^(BOOL finished){
}];
[UIView animationWithDuration:duration delay:delay options:(UIViewAnimationOptions) animations:^{
} completion:^(BOOL finished){
}];
// 其中options選項常用如下
UIViewAnimationOptionCurveEaseInOut(開始由慢到快,結束由快到慢)
UIViewAnimationOptionCurveEaseIn(由慢到快)
UIViewAnimationOptionCurveEaseOut(由快到慢)
UIViewAnimationOptionCurveEaseLinear(線性)

關閉動畫

[UIView setAnimationsEnabled:NO];  // 整個應用程序中的UIView動畫都會失效;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章