前言:
核心動(dòng)畫是iOS中一個(gè)渲染和動(dòng)畫的基礎(chǔ)設(shè)施行拢,你可以用它來(lái)為你的應(yīng)用做基礎(chǔ)的動(dòng)畫效果。在核心動(dòng)畫中邢享,你要做的只是配置一些動(dòng)畫參數(shù)始衅,接下來(lái)的任務(wù)就可以交給核心動(dòng)畫來(lái)處理了,很方便是吧议双。下面是核心動(dòng)畫在系統(tǒng)的層次結(jié)構(gòu):
CoreAnimation
CAAnimation
是一個(gè)抽象的動(dòng)畫類痘番,他提供基本的支持給CAMediaTiming
和CAAction
。給Layer
添加動(dòng)畫,你也可以使用子類CABasicAnimation
,CAKeyframeAnimation
, CAAnimationGroup
, 和 CATransition
.
CAAnimation
CAMediaTimingFunction
是一個(gè)控制動(dòng)畫節(jié)奏的可選的時(shí)間函數(shù)汞舱。它的初始化以下面的初始化方式構(gòu)造對(duì)象:
+ (instancetype)functionWithName:(NSString *)name;
/** Timing function names. **/
CA_EXTERN NSString * const kCAMediaTimingFunctionLinear
__OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);
CA_EXTERN NSString * const kCAMediaTimingFunctionEaseIn
__OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);
CA_EXTERN NSString * const kCAMediaTimingFunctionEaseOut
__OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);
CA_EXTERN NSString * const kCAMediaTimingFunctionEaseInEaseOut
__OSX_AVAILABLE_STARTING (__MAC_10_5, __IPHONE_2_0);
CA_EXTERN NSString * const kCAMediaTimingFunctionDefault
__OSX_AVAILABLE_STARTING (__MAC_10_6, __IPHONE_3_0);
具體的效果可以看下面的圖伍纫。kCAMediaTimingFunctionDefault
是系統(tǒng)默認(rèn)的時(shí)間函數(shù)。使用這個(gè)函數(shù)來(lái)確保你的動(dòng)畫時(shí)間匹配大多數(shù)系統(tǒng)的動(dòng)畫昂芜。
你可以對(duì)應(yīng)上圖看下面的效果:
你可以點(diǎn)擊這里是獲取CAMediaTimingFunction
更多相關(guān)內(nèi)容莹规。你也可以點(diǎn)擊這里自己去操作一下相關(guān)內(nèi)容。
CAAnimationDelegate
每個(gè)動(dòng)畫都有一個(gè)delegate
,會(huì)回調(diào)給你一個(gè)動(dòng)畫開(kāi)始和動(dòng)畫結(jié)束的協(xié)議泌神。方便為你的應(yīng)用做相應(yīng)的處理良漱。在動(dòng)畫結(jié)束后你應(yīng)該為layer
使用removeAllAnimations
移除相應(yīng)的動(dòng)畫,減小不必要的開(kāi)銷欢际。
#pragma mark - CAAnimationDelegate
- (void)animationDidStart:(CAAnimation *)anim{
NSLog(@"動(dòng)畫開(kāi)始");
}
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
/*
因?yàn)槲覀兊膭?dòng)畫repeatCount屬性設(shè)置成了1000母市。所以會(huì)很久才結(jié)束。你可以手動(dòng)修改
你可以根據(jù)"key值來(lái)判斷是哪個(gè)layer上的動(dòng)畫"
比如:[XXX.arrowLayer animationForKey:@"positionX"]拿到動(dòng)畫
*/
NSLog(@"動(dòng)畫結(jié)束");
}
具體相關(guān)的內(nèi)容可以見(jiàn)demo中的CAAnimationViewController
CAPropertyAnimation
CAPropertyAnimation
是CAAnimation
的子類损趋,創(chuàng)造動(dòng)畫的時(shí)候以key-path
操作相關(guān)視圖層的屬性來(lái)完成動(dòng)畫患久。
完整的key-path
請(qǐng)點(diǎn)擊這里
具體使用key-path
操作可以見(jiàn)demo中的CAPropertyAnimationViewController
。
屬性值
**additive** 決定是否把動(dòng)畫指定的值添加到當(dāng)前render tree 來(lái)產(chǎn)生新的render tree值舶沿。
additive
的解釋還是太過(guò)于生硬墙杯,你需要知道layer tree
(見(jiàn)最下面的layer tree模塊)。在動(dòng)畫的時(shí)候設(shè)置additive
YES后會(huì)把當(dāng)前的presentation layer
加入到render tree
括荡。
CABasicAnimation
CABasicAnimation
對(duì)象為layer
提供基本的高镐,單一的frame有關(guān)的動(dòng)畫。CABasicAnimation里面需要注意fromValue
畸冲,byValue
嫉髓,toValue
屬性控制
設(shè)置預(yù)備的參數(shù):
組合參數(shù)(不為nil) | 區(qū)間值 |
---|---|
fromValue + toValue | [fromValue,toValue] |
fromValue + byValue | [fromValue,fromValue + byValue] |
byValue + toValue | [toValue - byValue,toValue] |
fromValue | [fromValue ,layer當(dāng)前設(shè)置的value] |
toValue | [layer當(dāng)前設(shè)置的value ,toValue] |
byValue | [layer當(dāng)前設(shè)置的value ,layer當(dāng)前設(shè)置的value + byValue] |
CAKeyframeAnimation
CAKeyframeAnimation
對(duì)象有能力為layer
對(duì)象提供關(guān)鍵幀動(dòng)畫。你可以通過(guò)指定一個(gè)儲(chǔ)存關(guān)鍵幀的數(shù)組來(lái)控制相應(yīng)的動(dòng)畫時(shí)間和動(dòng)畫行為邑闲。
屬性值
**values** 一個(gè)承載動(dòng)畫多個(gè)關(guān)鍵幀值的數(shù)組
**keyTimes** 一個(gè)承載動(dòng)畫時(shí)間的數(shù)組算行。數(shù)據(jù)的每個(gè)值都在0-1之間,第一個(gè)值為0最后的一個(gè)值為1苫耸。數(shù)組的值對(duì)應(yīng)關(guān)鍵幀數(shù)組的值或者是path路勁的屬性
**path** 一段CGPathRef路徑州邢。layer沿著路勁動(dòng)畫。如果你同時(shí)設(shè)置了values 和path褪子,path路勁將會(huì)被執(zhí)行量淌。path擁有更高的優(yōu)先權(quán)。
具體使用方法可以見(jiàn)demo中的CAKeyframeAnimationViewController
嫌褪,雪人是按照path
路徑呀枢,社交圖標(biāo)是按照values
效果:
CATransaction
對(duì)layer
每一次的修改都是事務(wù)的一部分。事物是通過(guò)CATransaction
類來(lái)管理的笼痛。CoreAnimation
支持兩種類型的事務(wù):隱式事務(wù)和顯式事務(wù)裙秋。CATransaction
類不是通過(guò)alloc init
方法來(lái)初始化琅拌。而是借助于begin
和commit
方法。
method:
**begin** 為當(dāng)前線程創(chuàng)建一個(gè)新的事務(wù)
**commit** 提交當(dāng)前的事務(wù)所有的改變項(xiàng)
看demo
中CATransactionViewController
類:
- (void)viewDidLoad{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"圣誕老人"]];
self.imageView.frame = CGRectMake(0, 0, 100, 100);
self.imageView.center = self.view.center;
[self.view addSubview:self.imageView];
self.redLayer = [CALayer layer];
self.redLayer.frame = CGRectMake(100, 100, 100, 100);
self.redLayer.delegate = self;
self.redLayer.backgroundColor = [UIColor redColor].CGColor;
[self.view.layer addSublayer:self.redLayer];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// configure the transaction
[CATransaction begin];
// [CATransaction setDisableActions:YES];
[CATransaction setAnimationDuration:4.0];
[CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
//set the position
self.redLayer.position = [[touches anyObject] locationInView:self.view];
self.imageView.layer.position = [[touches anyObject] locationInView:self.view];
//commit transaction
[CATransaction commit];
NSLog(@"Outside: %@", [self.imageView actionForLayer:self.imageView.layer forKey:@"position"]);
//begin animation block
[UIView beginAnimations:nil context:nil];
//test layer action when inside of animation block
NSLog(@"Inside: %@", [self.imageView actionForLayer:self.imageView.layer forKey:@"position"]);
//end animation block
[UIView commitAnimations];
}
紅色的視圖是layer
.圣誕老人是UIImageView
摘刑。當(dāng)點(diǎn)擊了其他區(qū)域进宝,你會(huì)發(fā)現(xiàn)紅色的視圖有一個(gè)緩慢的動(dòng)畫,而圣誕老人馬上就到了指定區(qū)域泣侮。這是因?yàn)?code>UIView的隱式動(dòng)畫被關(guān)聯(lián)圖層給禁用了即彪。
對(duì)于layer
圖層你還可以利用下面方法禁用隱式動(dòng)畫。
[CATransaction setDisableActions:YES];
更多信息你可以點(diǎn)擊這里去了解活尊。也建議讀讀喵大翻譯的View-Layer 協(xié)作.
CAAnimationGroup
CAAnimationGroup
和CAPropertyAnimation
一樣是CAAnimation
的子類隶校。CAAnimationGroup
可以讓多個(gè)動(dòng)畫組合同時(shí)發(fā)生。
Important
The delegate and removedOnCompletion properties of animations in the [animations
](https://developer.apple.com/reference/quartzcore/caanimationgroup/1412516-animations?language=objc) array are currently ignored. The CAAnimationGroup
delegate does receive these messages.
layer tree
核心動(dòng)畫中有三種layer tree
蛹锰。每一種layer tree
在你的應(yīng)用呈現(xiàn)在屏幕中扮演著不同的角色深胳。
- model layer tree (就是我們應(yīng)用通常使用最多的layer對(duì)象,他們?yōu)閯?dòng)畫儲(chǔ)存著目標(biāo)值。比如:position,paque等)
- presentation tree(這些layer對(duì)象呈現(xiàn)著一個(gè)動(dòng)畫當(dāng)前值铜犬。比如你的layer沿著x軸歷時(shí)5秒從0到5model layer position會(huì)一直顯示最后的值5舞终,而presentation隨著時(shí)間顯示0,1,2..5。注意你不應(yīng)該人為去修改這些值癣猾。)
- render tree(這種layer對(duì)象在實(shí)際的動(dòng)畫中,但它對(duì)核心動(dòng)畫來(lái)說(shuō)是私有的敛劝,無(wú)法操作的)
我們來(lái)驗(yàn)證下,在例子中的LayerTreeViewController
類中加入下面的代碼:
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.redView.layer.position = CGPointMake(100, 100);
[self printMethod];
CABasicAnimation *basicAnimation = [[CABasicAnimation alloc] init];
basicAnimation.keyPath = @"position.y";
basicAnimation.fromValue = @0;
basicAnimation.toValue = @500;
basicAnimation.duration = 10;
[self.redView.layer addAnimation:basicAnimation forKey:@"positionY"];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0f
target:self
selector:@selector(printMethod)
userInfo:nil
repeats:YES];
[timer fire];
}
- (void)printMethod{
CALayer *modelLayer = self.redView.layer;
CALayer *presentationLayer = self.redView.layer.presentationLayer;
NSLog(@"model layer:%@ presentation layer :%@", NSStringFromCGPoint(modelLayer.position),NSStringFromCGPoint(presentationLayer.position));
}
#pragma mark - get
- (UIView *)redView{
if (!_redView) {
_redView = [[UIView alloc] init];
_redView.frame = CGRectMake(0, 0, 100, 100);
_redView.backgroundColor = [UIColor redColor];
_redView.center = self.view.center;
[self.view addSubview:_redView];
[self printMethod];
}
return _redView;
}
看看打印結(jié)果:
可以看出presentation layer
初始值為(0纷宇,0)夸盟。當(dāng)我們手動(dòng)的去改變postion
值,presentation layer
沒(méi)有發(fā)現(xiàn)變化而model layer
發(fā)生了改變像捶。在使用動(dòng)畫的時(shí)候presentation layer
才發(fā)生變化上陕,代表在動(dòng)畫中layer
實(shí)時(shí)的值。
更多了解您可以點(diǎn)擊Demo拓春。