iOS動畫——CoreAnimation

CoreAnimation
在我以前的UIKit動畫裏面簡單的提了一句CoreAnimation動畫,其實你們別看它類庫名種有個animation,實際上animation在這個庫中只佔有很小的地位。
多線程

像咱們常常用的邊框、圓角、陰影、錨點等等這些屬性都是有CA提供的。動畫

在說CA動畫前,咱們先說一下CALayer這個類,CALayer能夠叫作圖層,UIView是視圖。對別CALayer和UIView它們之間最大的差異在於CALayer是不處理交互的,好比點擊事件等。spa

實際上UIView是CALayer的高層封裝罷了,UIView的現實、繪圖、動畫等等都是封裝的CALayer,在CALayer中有個重要的屬性叫作affineTransform(放射變換),其實它和UIView中的transform是一摸同樣的,返回的都是線程

CAAffineTransform。當你改變過一個view.transform屬性或者view.layer.transform的時候須要恢復默認狀態的話,記得先把他 們重置可使用代理

view.transform = CGAffineTransformIdentity,或者view.layer.transform =CATransform3DIdentity,假設你一直不斷的改變一個view.transform的屬性,而每次改變以前沒有重置的話,你會發現後來 的改變和你想要的發生變化了,不是你真正想要的結果。code

如今你們對CALayer有了初步的認識,咱們一塊兒看看動畫在CA中是如何使用的。orm

 

隱式動畫對象

其實咱們只要修改CALayer中和動畫有關的屬性,就算咱們不寫動畫代碼,在運行的時候也是會有動畫效果的。這叫作隱式動畫,也就是咱們並無明顯的調用。blog

下面咱們看個例子事件

@interface ViewController ()
{
    CALayer *_viewLayer;
}
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    _viewLayer = [CALayer layer];
    _viewLayer.frame = CGRectMake(0, 0, 100, 100);
    [_viewLayer setBackgroundColor:[UIColor greenColor].CGColor];
    _viewLayer.opacity = 0.25;
    [self.view.layer addSublayer:_viewLayer];
    
    // Do any additional setup after loading the view, typically from a nib.
}

- (IBAction)click:(id)sender
{
    CGAffineTransform moveTransforam = CGAffineTransformMakeTranslation(180, 200);
    [_viewLayer setAffineTransform:moveTransforam];
    _viewLayer.opacity = 1;
}

 

把這段代碼輸入,點擊按鈕,你就會發現view逐漸的變的不透明,而且位置也發生了改變。

 

顯式動畫

在顯式動畫中,不須要修改屬性和調用動畫執行方法,只須要經過CABasicAnimation逐個定義就好了,每一個對象有持續時間、重複次數等屬性,而後使用addAnimation:forkey:方法分別將每一個動畫用到圖層的特定屬性中。

可以作動畫的圖層屬性有如下:

opacity;

transform.scale;

transform.scale.x;

transform.scale.y;

transform.rotation.z;

opacity;

margin;

zPosition;

backgroundColor;

cornerRadius;

bounds;

contents;

contentsRect;

frame;

hidden;

mask;

masksToBounds;

position;

shadowColor;

shadowOffset;

shadowOpacity;

shadowRadius;

下面咱們看一個顯式動畫的例子:

    CABasicAnimation *opAnim = [CABasicAnimation animationWithKeyPath:@"opacity"];
    opAnim.duration = 3.0;
    opAnim.fromValue = [NSNumber numberWithFloat:.25];
    opAnim.toValue = [NSNumber numberWithFloat:1.0];
    opAnim.cumulative = NO;
    opAnim.repeatCount = 2;
    opAnim.fillMode = kCAFillModeForwards;
    opAnim.removedOnCompletion = NO;
    [_viewLayer addAnimation:opAnim forKey:@"animateOpacity"];
    
    CGAffineTransform moveTransform = CGAffineTransformMakeTranslation(180, 200);
    CABasicAnimation *moveAnim = [CABasicAnimation animationWithKeyPath:@"transform"];
    moveAnim.duration = 6.0;
    moveAnim.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeAffineTransform(moveTransform)];
    moveAnim.fillMode = kCAFillModeForwards;
    moveAnim.removedOnCompletion = NO;
    moveAnim.delegate = self;
    moveAnim.repeatCount = 2;
    [_viewLayer addAnimation:moveAnim forKey:@"animateTransform"];

 

把click中的代碼換成上面的代碼,會發現視圖慢慢變得不透明,過程當中執行兩次。

下面看一下CABasicAnimation屬性有哪些做用:

屬性 描述
duration 動畫持續時間
fromValue 動畫的屬性起始值
toValue 動畫的屬性目標值
cumulative 是否保留上次動畫的值
repeatCount 重複次數
fillMode 使用動畫後不在返回原位置
removeOnCompletion 動畫完成後移除動畫狀態
delegate 動畫代理

 

 

 

 

 

 

 

 

 

這裏簡單說一下cumulative,上面例子若是cumulative設爲YES的話,就不會執行第二次的opacity的變化了,由於保留了動畫的狀態。

fillMode和removeOnCompletion一塊兒用使得動畫結束後視圖還在結束的位置,不然視圖會回到原始位置。

不過這裏說一下,雖然咱們看到的值是已經變了,可是實際上原始值並不會由於作了動畫而改變,只不過是affineTransform變了,若是要屢次作affineTransform就要像上面說的,須要讓它恢復初始值就不會出問題。

而後再來看看delegate,不過代理不是CABasicAnimation的,也不是它的父類CAPropertyAnimation的,而是它父類的父類CAAnimation的!

代理方法以下

- (void)animationDidStart:(CAAnimation *)anim;
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;

 

一個是動畫是在動畫開始時的回調,另外一個是在動畫結束後的回調。

 

關鍵幀動畫

關鍵幀動畫其實也能夠說又分兩種,一種是幀動畫一種是路徑動畫。

幀動畫,很少說先看例子

    CAKeyframeAnimation *opAnim = [CAKeyframeAnimation animationWithKeyPath:@"opacity"];
    opAnim.duration = 6.0;
    opAnim.values = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.25],[NSNumber numberWithFloat:0.75],[NSNumber numberWithFloat:1.0], nil];
    opAnim.keyTimes = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0],[NSNumber numberWithFloat:0.5],[NSNumber numberWithFloat:1.0], nil];
    
    opAnim.fillMode = kCAFillModeForwards;
    opAnim.removedOnCompletion = NO;
    opAnim.delegate = self;
    [_viewLayer addAnimation:opAnim forKey:@"animateOpacity"];

 

這裏咱們對透明度作動畫,分別在values和keyTimes裏面設置了到達某一時間應該到達的值,也就是經過這些值影響了在不一樣時間動畫的狀態不同。你們應該還記得在以前的UIKit動畫中,介紹過keyframe開始和持續時間的含義,它們都是總時間的百分比。

路徑動畫

路徑動畫動畫其實能夠說是特殊的幀動畫,首先動畫的對象屬性是position,而後每一幀的速率都相同,用多線程的概念來說大概就是串行執行動畫的意思。

    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, NULL, 160.f, 100.f);
    CGPathAddLineToPoint(path, NULL, 100.f, 280.f);
    CGPathAddLineToPoint(path, NULL, 260.f, 170.f);
    CGPathAddLineToPoint(path, NULL, 60.f, 170.f);
    CGPathAddLineToPoint(path, NULL, 220.f, 280.f);
    CGPathCloseSubpath(path);

    CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    [anim setDuration:10.f];
    [anim setDelegate:self];
    [anim setPath:path];
    CFRelease(path);
    path = nil;
    [_viewLayer addAnimation:anim forKey:@"position"];

 

這裏用CGMutablePathRef來產生路徑上下文,其實CGMutablePathRef和繪圖時的CGContextRef差很少。

下面設置再也不是針對values和keyTimes了,而是設置它的path屬性。

最後不要忘了釋放CGMutablePathRef,由於它是CoreFoundation對象沒有采用ARC因此要手動管理內存。

相關文章
相關標籤/搜索