Core Animation 學習筆記(二)
1.專用圖層(Specialized Layers)
常用的圖層大概有下面這幾個:
CAShapeLayer
CATextLayer
CATransformLayer
CAGradientLayer
CAReplicatorLayer
CAScrollLayer
CATiledLayer
CAEmitterLayer
CAEAGLLayer
AVPlayerLayer
目前我隻用過其中的幾個,就簡單講講自己用過的吧!
(1)CAShapeLayer是一個通過矢量圖形而不是bitmap來繪制的圖層子類。你指定諸如顔色和線寬等屬性,用CGPath來定義想要繪制的圖形,最後CAShapeLayer就會自動渲染出來。通常使用CAShapeLayer結合UIBezierPath繪制簡單圖形。用CAShapeLayer可以為每個角指定是否圓角。
下面這段代碼繪制了一個有三個圓角一個直角的矩形:
// 定義路徑參數
CGRect rect = CGRectMake(50, 50, 100, 100);
CGSize radii = CGSizeMake(20, 20);
UIRectCorner corners = UIRectCornerTopRight | UIRectCornerBottomRight | UIRectCornerBottomLeft;
// 建立路徑
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:corners cornerRadii:radii];
(2)CAGradientLayer是用來生成兩種或更多顔色平滑漸變的。用Core Graphics複制一個CAGradientLayer并将内容繪制到一個普通圖層的寄宿圖也可以實作這個效果,但是CAGradientLayer的真正好處在于繪制使用了硬體加速。使用CAGradientLayer不僅可以實作基礎漸變(一種顔色漸變到另一種顔色),還能實作多重漸變(一種顔色漸變到多種顔色)。下面是一段多種漸變的例子:
- (void)viewDidLoad {
[super viewDidLoad];
// 建立梯度圖層并添加到容器視圖上
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = self.containerView.bounds;
[self.containerView.layer addSublayer:gradientLayer];
// 設定梯度顔色
gradientLayer.colors = @[(__bridge id)[UIColor redColor].CGColor, (__bridge id [UIColor yellowColor].CGColor, (__bridge id)[UIColor greenColor].CGColor];
// 設定位置
gradientLayer.locations = @[@0.0, @0.25, @0.5];
// 設定梯度開始和結束點
gradientLayer.startPoint = CGPointMake(0, 0);
gradientLayer.endPoint = CGPointMake(1, 1);
}
(3)CAReplicatorLayer可以高效生成許多相似的圖層。它會繪制一個或多個圖層的子圖層,并在每個 複制體上應用不同的變換。變換是逐漸增加的,每個執行個體都是相 對于前一執行個體布局。這就是為什麼這些複制體最終不會出現在同意位置上.使用CAReplicatorLayer和CAGradientLayer可以實作倒影的效果。
2.隐式動畫(Implicit Animations)
當改變CALayer那個是否可以做動畫的屬性時,并不能立刻在螢幕上展現出來。相反,它是從先前的值平滑過渡到新的值。這一切都是預設的行為,你不需要做額外的操作。例如改變圖層顔色
self.colorLayer.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0].CGColor;
這其實就是所謂的隐式動畫。之是以叫内聯是因為我們并沒有指定任何動畫的類型。改變了一個屬性,然後Core Animation來決定如何并且何時去做動畫。
(1)事務
事務指的是Core Animation用來包含一系列屬性動畫集合的機制,任何用指定事務去改變做動畫的圖層,屬性都不會立刻發生變化,而是當事務一旦送出的時候開始用一個動畫過渡到新值。使用CATransaction控制動畫時間
- (IBAction)changeColor
{
// 開始一個新的事務
[CATransaction begin];
// 設定1秒的動畫
[CATransaction setAnimationDuration:1.0];
// 随機給背景配色
CGFloat red = arc4random() / (CGFloat)INT_MAX;
CGFloat green = arc4random() / (CGFloat)INT_MAX;
CGFloat blue = arc4random() / (CGFloat)INT_MAX;
self.colorLayer.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0].CGColor;
// 送出事務
[CATransaction commit];
}
注意:UIView關聯的圖層禁用了隐式動畫,對這種圖層做動畫的唯一辦法就是使用UIView的動畫函數。
3.顯示動畫(Implicit Animations)
(1)屬性動畫
動畫其實就是一段時間内發生的改變,最簡單的形式就是從一個值改變到另一個值,這也是CABasicAnimation最主要的功能。
- (IBAction)changeColor
{
// 建立一個新的随機顔色
CGFloat red = arc4random() / (CGFloat)INT_MAX;
CGFloat green = arc4random() / (CGFloat)INT_MAX;
CGFloat blue = arc4random() / (CGFloat)INT_MAX;
UIColor *color = [UIColor colorWithRed:red green:green blue:blue alpha:1.0];
// 建立一個基本動畫
CABasicAnimation *animation = [CABasicAnimation animation];
animation.keyPath = @"backgroundColor";
animation.toValue = (__bridge id)color.CGColor;
// 在圖層上設定動畫
[self.colorLayer addAnimation:animation forKey:nil];
}
運作程式,結果有點差強人意,點選按鈕,的确可以使圖層動畫過渡到一個新的顔色,然動畫結束之後又立刻變回原始值。
這是因為動畫并沒有改變圖層的模型,而隻是展現。一旦動畫結束并從圖層上移除之後,圖層就立刻恢複到之前定義的外觀狀态。我們從沒改變過backgroundColor屬性,是以圖層就傳回到原始的顔色。
(2)CAKeyframeAnimation是另一種UIKit沒有暴露但功能強大的類。CAKeyframeAnimation提供了關鍵節點的幀,然後Core Animation在非關鍵位置對每幀之間進行自動處理
(3)CAAnimationGroup可以把這些動畫組合在一起形成一個動畫組。
(4)過渡(CATransition)
屬性動畫隻對圖層的可動畫屬性起作用,是以如果要改變一個不能動畫的屬性(比如圖檔),或者從層級關系中添加或者移除圖層,屬性動畫将不起作用。于是就有了過渡。過渡并不像屬性動畫那樣平滑地在兩個值之間做動畫,而是影響到整個圖層的變化。過渡動畫首先展示之前的圖層外觀,然後通過一個交換過渡到新的外觀。CATransition隻提供了四種預設動畫類型,太少了。但是蘋果通過UIView +transitionFromView:toView:duration:options:completion:和+transitionWithView:duration:options:animations:方法提供了Core Animation的過渡特性。UIView過渡方法中options參數可以由如下常量指定:
UIViewAnimationOptionTransitionFlipFromLeft
UIViewAnimationOptionTransitionFlipFromRight
UIViewAnimationOptionTransitionCurlUp
UIViewAnimationOptionTransitionCurlDown
UIViewAnimationOptionTransitionCrossDissolve
UIViewAnimationOptionTransitionFlipFromTop
UIViewAnimationOptionTransitionFlipFromBotto
小例子:用renderInContext:建立自定義過渡效果
@implementation ViewController
- (IBAction)performTransition
{
// 截圖
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, YES, 0.0);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *coverImage = UIGraphicsGetImageFromCurrentImageContext();
// 插入截圖
UIView *coverView = [[UIImageView alloc] initWithImage:coverImage];
coverView.frame = self.view.bounds;
[self.view addSubview:coverView];
// 更新視圖(設定一個随機的背景色)
CGFloat red = arc4random() / (CGFloat)INT_MAX;
CGFloat green = arc4random() / (CGFloat)INT_MAX;
CGFloat blue = arc4random() / (CGFloat)INT_MAX;
self.view.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0];
// 做自定義動畫
[UIView animateWithDuration:1.0 animations:^{
// 放縮旋轉和淡入淡出
CGAffineTransform transform = CGAffineTransformMakeScale(0.01, 0.01);
transform = CGAffineTransformRotate(transform, M_PI_2);
coverView.transform = transform;
coverView.alpha = 0.0;
} completion:^(BOOL finished) {
// 動畫結束移除覆寫層
[coverView removeFromSuperview];
}];
}
@end
最後附上我看過的一本關于Core Animation的書籍《Core Animation Advanced Technology》,還要感謝“代碼蘿蔔”的部落格Core Animation Advanced Technique 學習筆記 - 代碼蘿蔔