CALayer包含在QuartzCore框架中,具有跨平台性,在iOS中使用Core Animation開發動畫的本質是 將CALayer內容轉化為位圖從而供硬件操作 。
//自定義圖層
CALayer *layer = [[CALayer alloc] init];
layer.bounds = CGRectMake(0, 0, PHOTO_HEIGHT, PHOTO_HEIGHT);
layer.position = CGPointMake(160, 200);
layer.backgroundColor = [UIColor redColor].CGColor;
layer.cornerRadius = PHOTO_HEIGHT/2;
//注意僅僅設置圓角,對於圖形而言可以正常顯示,但是對於圖層中繪制的圖片無法正確顯示,當繪制一張圖片到圖層上的時候會重新創建一個圖層添加到當前圖層
//如果想要正確顯示則必須設置masksToBounds = YES,剪切子圖層
layer.masksToBounds = YES;
//設置邊框
layer.borderColor = [UIColor whiteColor].CGColor;
layer.borderWidth = 2;
//設置圖層代理
layer.delegate = self;
//添加圖層到根圖層
[self.view.layer addSublayer:layer];
//調用圖層setNeedDisplay,否則代理方法不會被調用
[layer setNeedsDisplay];
注意:陰影效果無法和masksToBounds同時使用,因為masksToBounds的目的就是剪切外邊框,而陰影效果剛好在外邊框
CAAnimation
:核心動畫的基類,不能直接使用,負責動畫運行時間、速度的控制,本身實現了CAMediaTiming協議。CAPropertyAnimation
:屬性動畫的基類(通過屬性進行動畫設置,注意是可動畫屬性),不能直接使用。CAAnimationGroup
:動畫組,動畫組是一種組合模式設計,可以通過動畫組來進行所有動畫行為的統一控制,組中所有動畫效果可以並發執行。CATransition
:轉場動畫,主要通過濾鏡進行動畫效果設置。CABasicAnimation
:基礎動畫,通過屬性修改進行動畫參數控制,只有初始狀態和結束狀態。CAKeyframeAnimation
:關鍵幀動畫,同樣是通過屬性進行動畫參數控制,但是同基礎動畫不同的是它可以有多個狀態控制。①. 初始化動畫並設置動畫屬性
②. 設置動畫屬性初始值(可以省略)、結束值以及其他動畫屬性
③. 給圖層添加動畫
#pragma mark 移動動畫
-(void)translatonAnimation:(CGPoint)location{
//1.創建動畫並指定動畫屬性
CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
//2.設置動畫屬性初始值和結束值
basicAnimation.fromValue = [NSValue valueWithCGPoint:CGPointZero];
basicAnimation.toValue = [NSValue valueWithCGPoint:location];
//設置其他動畫屬性
basicAnimation.delegate = self;//設置代理
basicAnimation.duration = 3.0;//動畫時間3秒
//basicAnimation.repeatCount = HUGE_VALF;//設置重復次數,HUGE_VALF可看做無窮大
//basicAnimation.removedOnCompletion = NO;//運行一次是否移除動畫
//3.添加動畫到圖層,注意key相當於給動畫進行命名,以後獲得該動畫時可以使用此名稱獲取
[_layer addAnimation:basicAnimation forKey:@"MYBasicAnimation_Translation"];
}
執行上面的移動動畫,會出現一個現象,那就是 動畫結束後圖層回到原來位置 ,這是為什麼呢?
因為圖層動畫的本質是圖層內部的內容轉化為位圖,經過硬件操作形成的動畫效果,其實圖層本身在動畫過程中沒有發生任何變化。
#pragma mark - 動畫代理方法
#pragma mark 動畫開始
-(void)animationDidStart:(CAAnimation *)anim{
if( [anim isKindOfClass:[CABasicAnimation class]] ) {
CABasicAnimation *baseAnima = (CABasicAnimation *)anim;
//使用key-value的方式保持終點位置坐標
[baseAnima setValue:baseAnima.toValue forKey:@"MTBasicAnimationLocation"];
}
}
#pragma mark 動畫結束
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
if( flag ) {
//取出終點位置坐標,進行設置
_layer.position = [[anim valueForKey:@"MTBasicAnimationLocation"] CGPointValue];
}
}
但這樣執行後又會出現另外一個問題,那就是動畫結束後它有一個先回到起點再移動到終點的短暫動畫效果,這是什麼原因呢?
是隱式動畫導致的,對於非根圖層,設置圖層的可動畫屬性會產生自動動畫效果(例如
position
,實際上除了frame
,其他屬性都是可動畫屬性),這種動畫效果稱為隱式動畫
CABasicAnimation
做動畫干嘛,直接設置圖層position
不就可以實現了嗎?答案是這種隱式動畫我們不好控制動畫時間等動畫屬性,它是系統自動幫我們實現的過渡動畫效果。在這裡我們要消除這種問題的話,可以使用事務CATransaction
暫時消除隱式動畫,只需要修改動畫結束的代理方法:
#pragma mark 動畫結束
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
if( flag ) {
[CATransaction begin];//開啟事務
[CATransaction setDisableActions:YES];//禁止隱式動畫
_layer.position = [[anim valueForKey:@"MTBasicAnimationLocation"] CGPointValue];
[CATransaction commit];//提交事務
}
}
關於事務CATransaction
和這節主題不太相關,就不細講,有興趣可以自己去蘋果官方文檔查看具體使用方式
#pragma mark 旋轉動畫
-(void)rotationAnimation{
//1.創建動畫並指定動畫屬性
CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
//2.設置動畫屬性初始值、結束值
basicAnimation.fromValue = [NSNumber numberWithFloat:M_PI_2];
basicAnimation.toValue = [NSNumber numberWithFloat:M_PI_2*3];
//設置其他動畫屬性
basicAnimation.duration = 6.0;
basicAnimation.autoreverses = true;//旋轉後再旋轉到原來的位置
//4.添加動畫到圖層,注意key相當於給動畫進行命名,以後獲得該動畫時可以使用此名稱獲取
[_layer addAnimation:basicAnimation forKey:@"MYBasicAnimation_Rotation"];
}
- 通過 設置不同的屬性值 進行關鍵幀控制
- 通過 繪制路徑 進行關鍵幀控制
下面是實例:
#pragma mark 關鍵幀動畫第一種方式
-(void)translationAnimation1{
//1.創建關鍵幀動畫並設置動畫屬性
CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
//2.設置關鍵幀,這裡有四個關鍵幀,對於關鍵幀動畫初始值不能省略
NSValue *key1 = [NSValue valueWithCGPoint:_layer.position];
NSValue *key2 = [NSValue valueWithCGPoint:CGPointMake(80, 220)];
NSValue *key3 = [NSValue valueWithCGPoint:CGPointMake(45, 300)];
NSValue *key4 = [NSValue valueWithCGPoint:CGPointMake(55, 400)];
NSArray *values = @[key1,key2,key3,key4];
keyframeAnimation.values = values;
//設置其他屬性
keyframeAnimation.duration = 8.0;
keyframeAnimation.beginTime = CACurrentMediaTime() + 2;//設置延遲2秒執行
//3.添加動畫到圖層,添加動畫後就會執行動畫
[_layer addAnimation:keyframeAnimation forKey:@"MYKeyframeAnimation_Position1"];
}
#pragma mark 關鍵幀動畫第二種方式
-(void)translationAnimation2{
//1.創建關鍵幀動畫並設置動畫屬性
CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
//2.設置路徑
//繪制貝塞爾曲線
CGPathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, _layer.position.x, _layer.position.y);//移動到起始點
CGPathAddCurveToPoint(path, NULL, 160, 280, -30, 300, 55, 400);//繪制二次貝塞爾曲線
keyframeAnimation.path = path;//設置path屬性
CGPathRelease(path);//釋放路徑對象
//設置其他屬性
keyframeAnimation.duration = 8.0;
keyframeAnimation.beginTime = CACurrentMediaTime() + 2;//設置延遲2秒執行
//3.添加動畫到圖層,添加動畫後就會執行動畫
[_layer addAnimation:keyframeAnimation forKey:@"MYKeyframeAnimation_Position2"];
}
就是多個動畫的組合,直接來代碼:
#pragma mark 創建動畫組
-(void)groupAnimation{
//1.創建動畫組
CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
//2.設置組中的動畫和其他屬性
CABasicAnimation *basicAnimation = [self rotationAnimation];//基本動畫
CAKeyframeAnimation *keyframeAnimation = [self translationAnimation];//關鍵幀動畫
animationGroup.animations = @[basicAnimation,keyframeAnimation];
animationGroup.delegate = self;
//設置動畫時間,如果動畫組中動畫已經設置過動畫屬性,則不再生效
animationGroup.duration = 10.0;
animationGroup.beginTime = CACurrentMediaTime() + 5;//延遲五秒執行
//3.給圖層添加動畫
[_layer addAnimation:animationGroup forKey:nil];
}
①. 創建轉場動畫
②. 設置轉場類型、子類型(可選)及其他屬性
③. 設置轉場後的新視圖並添加動畫到圖層
#pragma mark 轉場動畫
-(void)transitionAnimation:(BOOL)isNext{
//1.創建轉場動畫對象
CATransition *transition = [[CATransition alloc] init];
//2.設置轉場類型,注意對於蘋果官方沒公開的動畫類型只能使用字符串,並沒有對應的常量定義
transition.type = @"cube";
//設置轉場方向類型
if (isNext) {
transition.subtype = kCATransitionFromRight;
}else{
transition.subtype = kCATransitionFromLeft;
}
//設置動畫時常
transition.duration = 1.0f;
//3.設置轉場後的新視圖添加轉場動畫
_imageView.image = [self getImage:isNext];
[_imageView.layer addAnimation:transition forKey:@"KCTransitionAnimation"];
}