?一智嚷、核心動畫結(jié)構(gòu)及定義
? ? ? Code Animation 中文翻譯為核心動畫馍悟,它是一組非常強的的動畫處理API狮含,是以它能做出非常炫麗的動畫效果柒傻,且往往事半功倍
? ? 核心動畫所處的位置入下圖所示:
? ? ? 可以看到孝赫,Code Animation位于UIKit的下一層,是作用在CALayer(Core Animation layer)上红符,相較于UIView動畫寒锚,它可以實現(xiàn)更復雜的動畫效果。
?? ?下邊我們看一下违孝,核心動畫的幾個類及結(jié)構(gòu)
下邊分析一下上圖結(jié)構(gòu):
**1.? CAMediaTiming** 協(xié)議中定義了時間,速度泳赋,重復次數(shù)等雌桑。屬性定義如下:
beginTime -> 用來設置動畫延時,若想延遲1秒祖今,就設置為CACurrentMediaTime()+1校坑,其中CACurrentMediaTime()為圖層當前時間拣技。
duration -> 動畫的持續(xù)時間。
speed -> 動畫速率耍目,決定動畫時間的倍率膏斤。當speed為2時,動畫時間為設置的duration的1/2邪驮。
timeOffset -> 動畫時間偏移量莫辨。比如設置動畫時長為3秒,當設置timeOffset為1.5時毅访,當前動畫會從中間位置開始沮榜,并在到達指定位置時,走完之前跳過的前半段動畫喻粹。
repeatCount -> 動畫的重復次數(shù)蟆融。
repeatDuration -> 動畫的重復時間。
autoreverses -> 動畫由初始值到最終值后守呜,是否反過來回到初始值的動畫型酥。如果設置為YES,就意味著動畫完成后會以動畫的形式回到初始值查乒。
fillMode -> 決定當前對象在非動畫時間段的行為.比如動畫開始之前弥喉,動畫結(jié)束之后。
(注:其實不只是CAAnimation遵循CAMediaTiming協(xié)議侣颂,熟悉底層結(jié)構(gòu)的小伙伴們應該知道CALayer也遵循這個協(xié)議档桃,所有在一定程度上我們可以通過控制layer本身的協(xié)議屬性來控制動畫節(jié)奏。)
**2. CAAnimation** 核心動畫基礎類憔晒,不能直接使用藻肄。除了CAMediaTiming協(xié)議中的方法,增加了CAAnimationDelegate的代理屬性等拒担。具體如下:
timingFunction -> 控制動畫的節(jié)奏嘹屯。系統(tǒng)提供的包括:kCAMediaTimingFunctionLinear (勻速),kCAMediaTimingFunctionEaseIn (慢進快出)从撼,kCAMediaTimingFunctionEaseOut (快進慢出)州弟,kCAMediaTimingFunctionEaseInEaseOut (慢進慢出,中間加速)低零,kCAMediaTimingFunctionDefault (默認)婆翔,當然也可通過自定義創(chuàng)建CAMediaTimingFunction。
delegate -> 代理掏婶。
removedOnCompletion -> 是否讓圖層保持顯示動畫執(zhí)行后的狀態(tài)啃奴,默認為YES,也就是動畫執(zhí)行完畢后從涂層上移除雄妥,恢復到執(zhí)行前的狀態(tài)最蕾,如果設置為NO依溯,并且設置fillMode為kCAFillModeForwards,則保持動畫執(zhí)行后的狀態(tài)瘟则。
**3. CATransition** 轉(zhuǎn)場動畫黎炉,系統(tǒng)提供了很多酷炫效果。屬性如下:
type -> 轉(zhuǎn)場動畫類型醋拧。
subtype -> 轉(zhuǎn)場動畫方向慷嗜。
startProgress -> 動畫起點進度(整體的百分比)。
endProgress -> 動畫終點進度(整體的百分比)趁仙。
filter -> 自定義轉(zhuǎn)場洪添。
**4.CAPropertyAnimation** 屬性動畫,針對對象的可動畫屬性進行效果的設置雀费,不可直接使用干奢。添加屬性具體如下:
keyPath -> CALayer的某個屬性名,并通過這個屬性的值進行修改盏袄,達到相應的動畫效果忿峻。
additive -> 屬性動畫是否以當前動畫效果為基礎,默認為NO辕羽。
cumulative -> 指定動畫是否為累加效果逛尚,默認為NO。
valueFunction -> 此屬性配合CALayer的transform屬性使用刁愿。
**5.CABasicAnimation**基礎動畫绰寞,通過keyPath對應屬性進行控制,需要設置fromValue以及toValue铣口。添加屬性如下:
fromValue -> keyPath相應屬性的初始值滤钱。
toValue -> keyPath相應屬性的結(jié)束值。
byValue -> 在不設置toValue時脑题,toValue = fromValue + byValue件缸,也就是在當前的位置上增加多少。
**6.CASpringAnimation** 帶有初始速度以及阻尼指數(shù)等物理參數(shù)的屬性動畫叔遂。我們可以把它看成在不絕對光滑的地面上他炊,一個彈簧拴著別小球,那么我們可以這么理解他的屬性(物理知識請問一下牛頓大叔):
mass -> 小球質(zhì)量已艰,影響慣性痊末。
stiffness -> 彈簧的勁度系數(shù)。
damping -> 阻尼系數(shù)哩掺,地面的摩擦力舌胶。
initialVelocity -> 初始速度,相當于給小球一個初始速度(可正可負疮丛,方向不同)
settlingDuration -> 結(jié)算時間幔嫂,根據(jù)上述參數(shù)計算出的預計時間,相對于你設置的時間誊薄,這個時間比較準確履恩。
**7.CAKeyframeAnimation** 關鍵幀動畫,同樣通過keyPath對應屬性進行控制呢蔫,但它可以通過values或者path進行多個階段的控制古涧。屬性如下:
values -> 關鍵幀組成的數(shù)組昨登,動畫會依次顯示其中的每一幀。
path -> 關鍵幀路徑,動畫進行的要素若皱,優(yōu)先級比values高,但是只對CALayer的anchorPoint和position起作用艘包。
keyTimes -> 每一幀對應的時間吊履,如果不設置,則各關鍵幀平分設定時間爷贫。
timingFunctions -> 每一幀對應的動畫節(jié)奏认然。
calculationMode -> 動畫的計算模式,系統(tǒng)提供了對應的幾種模式漫萄。
tensionValues -> 動畫張力控制卷员。
continuityValues -> 動畫連續(xù)性控制。
biasValues -> 動畫偏差率控制腾务。
rotationMode -> 動畫沿路徑旋轉(zhuǎn)方式毕骡,系統(tǒng)提供了兩種模式。
**8.CAAnimationGroup** 動畫組岩瘦,方便對于多動畫的統(tǒng)一控制管理未巫。
animations -> 所有動畫效果元素的數(shù)組。
?二 担钮、方法與代碼示例
**1橱赠、CABasicAnimation**
在一般的應用開發(fā)中,基礎動畫可以滿足大部分的開發(fā)需求箫津,主要完成對于對象指定動畫屬性兩個Value之間的動畫過度狭姨。
+(instancetype)animationWithKeyPath:(nullable NSString *)path;
**path:**CALayer的某個屬性名,并通過這個屬性的值進行修改苏遥,達到相應的動畫效果饼拍。下為可選參數(shù):
>? CATransform3D Key Paths :
> 旋轉(zhuǎn)
> transform.rotation.z
> rotation.x
> rotation.y
> rotation.z
> rotation
>
> 縮放
> scale.x
> scale.y
> scale.z
> scale
>
> 平移
> translation.x
> translation.y
> translation.z
> translation
>
> 位置
> CGPoint Key Paths:position.x
> x
> y
>
> 位置及大小
> CGRect Key Paths :
> bounds.size.width
> origin.x
> origin.y
> origin
> size.width
> size.height
> size
>?
> opacity 透明度
> backgroundColor 背景色
> cornerRadius? 圓角
> borderWidth? 邊距線寬
> contents? ? ? 內(nèi)容
>? ?
> 陰影
> Shadow Key Path:
>? shadowColor
>? shadowOffset
>? shadowOpacity
>? shadowRadius
代碼示例:
> -(void)basicAnimationWithTag:(NSInteger)tag{
>? ? CABasicAnimation *basicAni = nil;
>? ? switch (tag) {
>? ? ? ? case 0:
>? ? ? ? ? ? //初始化動畫并設置keyPath
>? ? ? ? ? ? basicAni = [CABasicAnimation animationWithKeyPath:@"position"];
>? ? ? ? ? ? //到達位置
>? ? ? ? ? ? basicAni.byValue = [NSValue valueWithCGPoint:CGPointMake(100, 100)];
>? ? ? ? ? ? break;
>? ? ? ? case 1:
>? ? ? ? ? ? basicAni = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
>? ? ? ? ? ? //到達縮放
>? ? ? ? ? ? basicAni.toValue = @(0.1f);
>? ? ? ? ? ? break;
>? ? ? ? case 2:
>? ? ? ? ? ? basicAni = [CABasicAnimation animationWithKeyPath:@"opacity"];
>? ? ? ? ? ? basicAni.toValue=@(0.1f);
>? ? ? ? ? ? break;
>? ? ? ? case 3:
>? ? ? ? ? ? basicAni = [CABasicAnimation animationWithKeyPath:@"transform"];
>? ? ? ? ? ? //3D
>? ? ? ? ? ? basicAni.toValue=[NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2+M_PI_4, 1, 1, 0)];
>? ? ? ? ? ? break;
>? ? ? ? case 4:
>? ? ? ? ? ? basicAni = [CABasicAnimation animationWithKeyPath:@"cornerRadius"];
>? ? ? ? ? ? //圓角
>? ? ? ? ? ? basicAni.toValue=@(50);
>? ? ? ? ? ? break;
>? ? ? ? default:
>? ? ? ? ? ? break;
>? ? }
>? ? //設置代理
>? ? basicAni.delegate = self;
>? ? //延時執(zhí)行
>? ? //basicAni.beginTime = CACurrentMediaTime() + 2;
>? ? //動畫時間
>? ? basicAni.duration = 1;
>? ? //動畫節(jié)奏
>? ? basicAni.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
>? ? //動畫速率
>? ? //basicAni.speed = 0.1;
>? ? //圖層是否顯示執(zhí)行后的動畫執(zhí)行后的位置以及狀態(tài)
>? ? //basicAni.removedOnCompletion = NO;
>? ? //basicAni.fillMode = kCAFillModeForwards;
>? ? //動畫完成后是否以動畫形式回到初始值
>? ? basicAni.autoreverses = YES;
>? ? //動畫時間偏移
>? ? //basicAni.timeOffset = 0.5;
>? ? //添加動畫
>? ? NSString *key = NSStringFromSelector(_cmd);
>? ? NSLog(@"動畫的key ======= %@",key);
>? ? [_animationLayer addAnimation:basicAni forKey:key];
> }
**2、CASpringAnimation**
CASpringAnimation是iOS9才引入的動畫類田炭,效果類似于UIView的spring動畫师抄,不過比其增加了質(zhì)量,勁度系數(shù)等屬性的擴展教硫,繼承于CABaseAnimation叨吮,用法也很簡單:
>? CASpringAnimation *springAni = [CASpringAnimation animationWithKeyPath:@"position"];
>? ? springAni.damping = 2;
>? ? springAni.stiffness = 50;
>? ? springAni.mass = 1;
>? ? springAni.initialVelocity = 2;
>? ? springAni.toValue = [NSValue valueWithCGPoint:CGPointMake(270, 350)];
>? ? springAni.duration = springAni.settlingDuration;
>? ? [_animationLayer addAnimation:springAni forKey:@"springAnimation"];
**3.CAKeyframeAnimation**
關鍵幀動畫和CABasicAnimation一樣是CApropertyAnimation的子類辆布,但是CABasicAnimation只能從一個數(shù)值(fromValue)變到另一個數(shù)值(toValue),而CAKeyframeAnimation使用values數(shù)組可以通過(keyTimes)設置多個關鍵幀茶鉴,同時可以利用path可以進行位置或者錨點的動畫操作锋玲。代碼如下
通過values設置
>? CAKeyframeAnimation *keyFrameAni = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];
> keyFrameAni.duration = 2;
> keyFrameAni.values = @[@(-(6) / 180.0*M_PI),@((6) / 180.0*M_PI),@(-(5) / 180.0*M_PI),@((5) / 180.0*M_PI),@(-(4) / 180.0*M_PI),@((4) / 180.0*M_PI),@(-(4) / 180.0*M_PI)];
> keyFrameAni.keyTimes = @[ @(0), @(0.225), @(0.425), @(0.6), @(0.75), @(0.875), @(1)];
> keyFrameAni.repeatCount = 2;
> [_animationLayer addAnimation:keyFrameAni forKey:@"keyFrameAnimation"];
通過path設置
? ? CAKeyframeAnimation *keyFrameAni = [CAKeyframeAnimation animationWithKeyPath:@"position"];
? ? UIBezierPath *path = [UIBezierPath bezierPath];
? ? [path moveToPoint:_animationLayer.position;
? ? [path addCurveToPoint:CGPointMake(300, 500) controlPoint1:CGPointMake(100, 400) controlPoint2:CGPointMake(270, 460)];
? ? keyFrameAni.path = path.CGPath;
? ? keyFrameAni.duration = 1;
? ? [_animationLayer addAnimation:keyFrameAni forKey:@"keyFrameAnimation"];
**4.CATransition**
轉(zhuǎn)場動畫是一種顯示樣式向另一種顯示樣式過渡的效果,能制作出酷炫的效果涵叮,不過謹慎使用私有API惭蹂,防止被拒的悲劇。
>? ? **type的enum值如下:**
>? ? kCATransitionFade 漸變
>? ? kCATransitionMoveIn 覆蓋
>? ? kCATransitionPush 推出
>? ? kCATransitionReveal 揭開
還有一些私有動畫類型割粮,效果很炫酷盾碗,不過不推薦使用。
subtype可取值:
>? ? **subtype的enum值如下:**
>? ? kCATransitionFromRight 從右邊
>? ? kCATransitionFromLeft 從左邊
>? ? kCATransitionFromTop 從頂部
>? ? kCATransitionFromBottom 從底部
代碼示例
>? ? ? CATransition *transtion = [CATransition animation];
>? ? transtion.duration = 1;
>? ? transtion.type = @"cube";
>? ? transtion.subtype = kCATransitionFromRight;//kCATransitionFromLeft? kCATransitionFromRight
>? ? _animationLayer.backgroundColor = [UIColor yellowColor].CGColor;
>? ? [_animationLayer addAnimation:transtion forKey:@"transtion"];
**5.CAAnimationGroup**
CAAnimationGroup 是一個動畫組舀瓢,使用Group可以將多個動畫合并一起加入到層中廷雅,Group中所有動畫并發(fā)執(zhí)行,可以方便地實現(xiàn)需要多種類型動畫的場景氢伟。
代碼示例
? ? //彈動動畫
? ? CAKeyframeAnimation *keyFrameAni = [CAKeyframeAnimation animationWithKeyPath:@"position.y"];
? ? CGFloat ty = _animationLayer.position.y;
? ? keyFrameAni.values = @[@(ty - 100),@(ty),@(ty - 50),@(ty)];
? ? //每一個動畫可以單獨設置時間和重復次數(shù),在動畫組的時間基礎上,控制單動畫的效果
? ? keyFrameAni.duration = 0.3;
? ? keyFrameAni.repeatCount= MAXFLOAT;
? ? keyFrameAni.delegate = self;
? ? //
? ? //圓角動畫
? ? CABasicAnimation *basicAni = [CABasicAnimation animationWithKeyPath:@"cornerRadius"];
? ? //到達位置
? ? basicAni.byValue = @(_animationLayer.bounds.size.width/2);
? ? //
? ? basicAni.duration = 1;
? ? basicAni.repeatCount = 1;
? ? //
? ? basicAni.removedOnCompletion = NO;
? ? basicAni.fillMode = kCAFillModeForwards;
? ? //設置代理
? ? basicAni.delegate = self;
? ? //動畫時間
? ? basicAni.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
? ? CAAnimationGroup *aniGroup = [CAAnimationGroup animation];
? ? aniGroup.animations = @[keyFrameAni,basicAni];
? ? aniGroup.autoreverses = YES;
? ? //動畫的表現(xiàn)時間和重復次數(shù)由動畫組設置的決定
? ? aniGroup.duration = 3;
? ? aniGroup.repeatCount=MAXFLOAT;
? ? //
? ? [_animationLayer addAnimation:aniGroup forKey:@"groupAnimation"];
三榜轿、動畫的暫停、恢復朵锣、加快及移除動畫
1谬盐、speed屬性是指當前層動畫的速率。用于將父時間縮放到本地時間诚些,例如飞傀。
如果速率為2,則本地時間的進展速度是父時間的兩倍诬烹。
我們可以通過設置speed =0來暫停動畫:
代碼示例:
?//獲取當前l(fā)ayer的動畫媒體時間
? ? CFTimeInterval interval = [_animationLayer convertTime:CACurrentMediaTime() toLayer:nil];
? ? //設置時間偏移量,保證停留在當前位置
? ? _animationLayer.timeOffset= interval;
? ? //暫定動畫
? ? _animationLayer.speed = 0;
設置speed =1來恢復動畫
代碼示例:
?//獲取暫停的時間
? ? CFTimeInterval beginTime = CACurrentMediaTime() - _animationLayer.timeOffset;
? ? //設置偏移量
? ? _animationLayer.timeOffset = 0;
? ? //設置開始時間
? ? _animationLayer.beginTime= beginTime;
? ? //開始動畫
? ? _animationLayer.speed = 1;
設置speed >1來加速動畫
代碼示例:
?_animationLayer.speed = 2;
2砸烦、動畫結(jié)束,我們可以移除動畫
[_animationLayer removeAllAnimations];//移除當前層所有動畫
? ? //[_animationLayer removeAnimationForKey:@"groupAnimation"];//移除當前層上名稱是groupAnimation的動畫
? 關于Code Animation 绞吁,就寫到這里了幢痘,附demo一份GitHub - Tony-iOS-Personal/AnimationDemo: 關于動畫的總結(jié)demo