iOS CAAnimation動(dòng)畫初探

先看看CAAnimation動(dòng)畫的繼承結(jié)構(gòu)

CAAnimation{

CAPropertyAnimation {

CABasicAnimation {

CASpringAnimation

}

CAKeyframeAnimation

}

CATransition

CAAnimationGroup

}

CAAnimation基本屬性詳解

//動(dòng)畫的動(dòng)作規(guī)則,包含以下值

//kCAMediaTimingFunctionLinear 勻速

//kCAMediaTimingFunctionEaseIn 慢進(jìn)快出

//kCAMediaTimingFunctionEaseOut 快進(jìn)慢出

//kCAMediaTimingFunctionEaseInEaseOut 慢進(jìn)慢出 中間加速

//kCAMediaTimingFunctionDefault 默認(rèn)

@property(nullable, strong) CAMediaTimingFunction *timingFunction;

//動(dòng)畫的代理回調(diào)

@property(nullable, strong) id delegate;

//動(dòng)畫執(zhí)行完以后是否移除動(dòng)畫,默認(rèn)YES

@property(getter=isRemovedOnCompletion) BOOL removedOnCompletion;

以上屬性詳解:

delegate:動(dòng)畫執(zhí)行的代理,在動(dòng)畫開始前設(shè)定,不用顯式的寫在代碼里,它包含兩個(gè)方法:

動(dòng)畫開始回調(diào)

- (void)animationDidStart:(CAAnimation *)aim;

動(dòng)畫結(jié)束回調(diào)

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

removedOnCompletion:動(dòng)畫完成后是否移除動(dòng)畫.默認(rèn)為YES.此屬性為YES時(shí), fillMode不可用,具體為什么不可用,可以自己結(jié)合兩個(gè)屬性分析一下,這里不再贅述.

timingFunction 設(shè)置動(dòng)畫速度曲線,默認(rèn)值上面已經(jīng)給出.下面說它的幾個(gè)方法:

這兩個(gè)方法是一樣的.如果我們對(duì)系統(tǒng)自帶的速度函數(shù)不滿意,可以通過這兩個(gè)函數(shù)創(chuàng)建一個(gè)自己喜歡的速度曲線函數(shù),具體用法可以參考這篇文章CAMediaTimingFunction的使用

+ (instancetype)functionWithControlPoints:(float)c1x :(float)c1y :(float)c2x :(float)c2y;

- (instancetype)initWithControlPoints:(float)c1x :(float)c1y :(float)c2x :(float)c2y;

獲取曲線函數(shù)的緩沖點(diǎn),具體用法可以參考這篇文章:iOS-核心動(dòng)畫高級(jí)編程/10-緩沖

- (void)getControlPointAtIndex:(size_t)idx values:(float[2])ptr;

CAAnimation協(xié)議的屬性

//開始時(shí)間.這個(gè)屬性比較復(fù)雜,傻瓜用法為:CACurrentMediaTime() + x,

//其中x為延遲時(shí)間.如果設(shè)置 beginTime = CACurrentMediaTime() + 1.0,產(chǎn)生的效果為延遲一秒執(zhí)行動(dòng)畫,下面詳解原理

@property CFTimeInterval beginTime;

//動(dòng)畫執(zhí)行時(shí)間,此屬性和speed有關(guān)系speed默認(rèn)為1.0,如果speed設(shè)置為2.0,那么動(dòng)畫執(zhí)行時(shí)間則為duration*(1.0/2.0).

@property CFTimeInterval duration;

//動(dòng)畫執(zhí)行速度,它duration的關(guān)系參考上面解釋

@property float speed;

//動(dòng)畫的時(shí)間延遲,這個(gè)屬性比較復(fù)雜,下面詳解

@property CFTimeInterval timeOffset;

//重復(fù)執(zhí)行次數(shù)

@property float repeatCount;

//重復(fù)執(zhí)行時(shí)間,此屬性優(yōu)先級(jí)大于repeatCount.也就是說如果repeatDuration設(shè)置為1秒重復(fù)10次,那么它會(huì)在1秒內(nèi)執(zhí)行完動(dòng)畫.

@property CFTimeInterval repeatDuration;

//是否自動(dòng)翻轉(zhuǎn)動(dòng)畫,默認(rèn)NO.如果設(shè)置YES,那么整個(gè)動(dòng)畫的執(zhí)行效果為A->B->A.

@property BOOL autoreverses;

//動(dòng)畫的填充方式,默認(rèn)為: kCAFillModeRemoved,包含以下值

//kCAFillModeForwards//動(dòng)畫結(jié)束后回到準(zhǔn)備狀態(tài)

//kCAFillModeBackwards//動(dòng)畫結(jié)束后保持最后狀態(tài)

//kCAFillModeBoth//動(dòng)畫結(jié)束后回到準(zhǔn)備狀態(tài),并保持最后狀態(tài)

//kCAFillModeRemoved//執(zhí)行完成移除動(dòng)畫

@property(copy) NSString *fillMode;

以上屬性的詳解:

beginTime:剛才上面簡單解釋了下這個(gè)屬性的用法:CACurrentMediaTime()+ x 會(huì)使動(dòng)畫延遲執(zhí)行x秒.不知道到這里有沒有人想過如果-x會(huì)出現(xiàn)怎么樣效果?假設(shè)我們有執(zhí)行一個(gè)3秒的動(dòng)畫,然后設(shè)置beginTime =? CACurrentMediaTime()- 1.5那么執(zhí)行動(dòng)畫你會(huì)發(fā)現(xiàn)動(dòng)畫只會(huì)執(zhí)行后半段,也就是只執(zhí)行后面的3-1.5s的動(dòng)畫.為什么會(huì)這樣?其實(shí)動(dòng)畫都有一個(gè)timeline(時(shí)間線)的概念.動(dòng)畫開始執(zhí)行都是基于這個(gè)時(shí)間線的絕對(duì)時(shí)間,這個(gè)時(shí)間和它的父類有關(guān)(系統(tǒng)的屬性注釋可以看到).默認(rèn)的CALayer的beginTime為零,如果這個(gè)值為零的話,系統(tǒng)會(huì)把它設(shè)置為CACurrentMediaTime(),那么這個(gè)時(shí)間就是正常執(zhí)行動(dòng)畫的時(shí)間:立即執(zhí)行.所以如果你設(shè)置beginTime=CACurrentMediaTime()+x;它會(huì)把它的執(zhí)行時(shí)間線推遲x秒,也就是晚執(zhí)行x秒,如果你beginTime=CACurrentMediaTime()-x;那它開始的時(shí)候會(huì)從你動(dòng)畫對(duì)應(yīng)的絕對(duì)時(shí)間開始執(zhí)行.

timeOffset:時(shí)間偏移量,默認(rèn)為0;既然它是時(shí)間偏移量,那么它即和動(dòng)畫時(shí)間相關(guān).這么解釋:假設(shè)我們?cè)O(shè)置一個(gè)動(dòng)畫時(shí)間為5s,動(dòng)畫執(zhí)行的過程為1->2->3->4->5,這時(shí)候如果你設(shè)置timeOffset = 2s那么它的執(zhí)行過程就會(huì)變成3->4->5->1->2如果你設(shè)置timeOffset = 4s那么它的執(zhí)行過程就會(huì)變成5->1->2->3->4,這么說應(yīng)該很明白了吧?

CAPropertyAnimation的基本屬性

//需要?jiǎng)赢嫷膶傩灾?/p>

@property(nullable, copy) NSString *keyPath;

//屬性動(dòng)畫是否以當(dāng)前動(dòng)畫效果為基礎(chǔ),默認(rèn)為NO

@property(getter=isAdditive) BOOL additive;

//指定動(dòng)畫是否為累加效果,默認(rèn)為NO

@property(getter=isCumulative) BOOL cumulative;

//此屬性相當(dāng)于CALayer中的transform屬性,下面會(huì)詳解

@property(nullable, strong) CAValueFunction *valueFunction;

以上屬性的詳解:

CAPropertyAnimation是屬性動(dòng)畫.顧名思義也就是針對(duì)屬性才可以做的動(dòng)畫.那它可以對(duì)誰的屬性可以做動(dòng)畫?是CALayer的屬性,比如:bounds,position等.那么問題來了,我們改變CALayer的position可以直接設(shè)置[CAPropertyAnimation animationWithKeyPath:@"position"]如果我們?cè)O(shè)置它的transform(CATransform3D)呢?CATransform3D是一個(gè)矩陣,如果我們想為它做動(dòng)畫怎么辦?下面這個(gè)屬性就是用來解決這個(gè)問題的.

valueFunction:我們來看它可以設(shè)置的值:

kCAValueFunctionRotateX

kCAValueFunctionRotateY

kCAValueFunctionRotateZ

kCAValueFunctionScale

kCAValueFunctionScaleX

kCAValueFunctionScaleY

kCAValueFunctionScaleZ

kCAValueFunctionTranslate

kCAValueFunctionTranslateX

kCAValueFunctionTranslateY

kCAValueFunctionTranslateZ

CAPropertyAnimation的方法

//通過key創(chuàng)建一個(gè)CAPropertyAnimation對(duì)象

+ (instancetype)animationWithKeyPath:(nullable NSString *)path;

下面我們來看一下可以設(shè)置屬性動(dòng)畫的屬性歸總:

CATransform3D{

rotation旋轉(zhuǎn)

transform.rotation.x

transform.rotation.y

transform.rotation.z

scale縮放

transform.scale.x

transform.scale.y

transform.scale.z

translation平移

transform.translation.x

transform.translation.y

transform.translation.z

}

CGPoint{

position

position.x

position.y

}

CGRect{

bounds

bounds.size

bounds.size.width

bounds.size.height

bounds.origin

bounds.origin.x

bounds.origin.y

}

property{

opacity

backgroundColor

cornerRadius

borderWidth

contents

Shadow{

shadowColor

shadowOffset

shadowOpacity

shadowRadius

}

}

總結(jié):CAAnimation是基類,CAPropertyAnimation**是抽象類,兩者都不可以直接使用, 那我們只有使用它的子類了.

CABasicAnimation基本動(dòng)畫

CABasicAnimation的屬性

//開始值

@property(nullable, strong) id fromValue;

//結(jié)束值

@property(nullable, strong) id toValue;

//結(jié)束值

@property(nullable, strong) id byValue;

這三個(gè)屬性之間的規(guī)則

fromValue和toValue不為空,動(dòng)畫的效果會(huì)從fromValue的值變化到toValue.

fromValue和byValue都不為空,動(dòng)畫的效果將會(huì)從fromValue變化到fromValue+byValue

toValue和byValue都不為空,動(dòng)畫的效果將會(huì)從toValue-byValue變化到toValue

只有fromValue的值不為空,動(dòng)畫的效果將會(huì)從fromValue的值變化到當(dāng)前的狀態(tài).

只有toValue的值不為空,動(dòng)畫的效果將會(huì)從當(dāng)前狀態(tài)的值變化到toValue的值.

只有byValue的值不為空,動(dòng)畫的效果將會(huì)從當(dāng)前的值變化到(當(dāng)前狀態(tài)的值+byValue)的值.

CABasicAnimation看起來不太復(fù)雜,但實(shí)際只用這個(gè)就足以可以做很多種動(dòng)畫了,下面簡單用一下,先看效果:


CABasicAnimation.gif

實(shí)現(xiàn)代碼:

- (IBAction)animation:(id)sender

{

UIButton *btn = (UIButton *)sender;

CABasicAnimation *animation = nil;

switch (btn.tag)

{

//淡如淡出

case 0:

animation = [CABasicAnimation animationWithKeyPath:@"opacity"];

[animation setFromValue:@1];

[animation setToValue:@0.1];

break;

//縮放

case 1:

animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];

[animation setFromValue:@1];

[animation setToValue:@0.1];

break;

//旋轉(zhuǎn)

case 2:

animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];

[animation setToValue:@(M_PI)];

break;

//平移

case 3:

animation = [CABasicAnimation animationWithKeyPath:@"position"];

[animation setToValue:[NSValue valueWithCGPoint:CGPointMake(self.opView.center.x, self.opView.center.y+200)]];

break;

default:

break;

}

animation.delegate = self;

animation.duration = 0.3;//設(shè)置動(dòng)畫時(shí)間,單次動(dòng)畫時(shí)間

animation.removedOnCompletion = NO;//默認(rèn)為YES,設(shè)置為NO時(shí)setFillMode有效

animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];

//設(shè)置自動(dòng)翻轉(zhuǎn)

//設(shè)置自動(dòng)翻轉(zhuǎn)以后單次動(dòng)畫時(shí)間不變,總動(dòng)畫時(shí)間增加一倍,它會(huì)讓你前半部分的動(dòng)畫以相反的方式動(dòng)畫過來

//比如說你設(shè)置執(zhí)行一次動(dòng)畫,從a到b時(shí)間為1秒,設(shè)置自動(dòng)翻轉(zhuǎn)以后動(dòng)畫的執(zhí)行方式為,先從a到b執(zhí)行一秒,然后從b到a再執(zhí)行一下動(dòng)畫結(jié)束

[animation setAutoreverses:YES];

//kCAFillModeForwards//動(dòng)畫結(jié)束后回到準(zhǔn)備狀態(tài)

//kCAFillModeBackwards//動(dòng)畫結(jié)束后保持最后狀態(tài)

//kCAFillModeBoth//動(dòng)畫結(jié)束后回到準(zhǔn)備狀態(tài),并保持最后狀態(tài)

//kCAFillModeRemoved//執(zhí)行完成移除動(dòng)畫

[animation setFillMode:kCAFillModeBoth];

//將動(dòng)畫添加到layer,添加到圖層開始執(zhí)行動(dòng)畫,

//注意:key值的設(shè)置與否會(huì)影響動(dòng)畫的效果

//如果不設(shè)置key值每次執(zhí)行都會(huì)創(chuàng)建一個(gè)動(dòng)畫,然后創(chuàng)建的動(dòng)畫會(huì)疊加在圖層上

//如果設(shè)置key值,系統(tǒng)執(zhí)行這個(gè)動(dòng)畫時(shí)會(huì)先檢查這個(gè)動(dòng)畫有沒有被創(chuàng)建,如果沒有的話就創(chuàng)建一個(gè),如果有的話就重新從頭開始執(zhí)行這個(gè)動(dòng)畫

//你可以通過key值獲取或者刪除一個(gè)動(dòng)畫:

[self.opView.layer addAnimation:animation forKey:@"baseanimation"];

}

CASpringAnimation彈性動(dòng)畫

CASpringAnimation的屬性(iOS9新加)

//理解下面的屬性的時(shí)候可以結(jié)合現(xiàn)實(shí)物理現(xiàn)象,比如把它想象成一個(gè)彈簧上掛著一個(gè)金屬小球

//質(zhì)量,振幅和質(zhì)量成反比

@property CGFloat mass;

//剛度系數(shù)(勁度系數(shù)/彈性系數(shù)),剛度系數(shù)越大,形變產(chǎn)生的力就越大,運(yùn)動(dòng)越快

@property CGFloat stiffness;

//阻尼系數(shù),阻止彈簧伸縮的系數(shù),阻尼系數(shù)越大,停止越快,可以認(rèn)為它是阻力系數(shù)

@property CGFloat damping;

//初始速率,動(dòng)畫視圖的初始速度大小速率為正數(shù)時(shí),速度方向與運(yùn)動(dòng)方向一致,速率為負(fù)數(shù)時(shí),速度方向與運(yùn)動(dòng)方向相反.

@property CGFloat initialVelocity;

//結(jié)算時(shí)間,只讀.返回彈簧動(dòng)畫到停止時(shí)的估算時(shí)間,根據(jù)當(dāng)前的動(dòng)畫參數(shù)估算通常彈簧動(dòng)畫的時(shí)間使用結(jié)算時(shí)間比較準(zhǔn)確

@property(readonly) CFTimeInterval settlingDuration;

下面我們寫一個(gè)demo看看效果:


實(shí)現(xiàn)代碼:

- (IBAction)animationBegin:(id)sender

{

UIButton *btn = (UIButton *)sender;

CASpringAnimation *springAnimation = [CASpringAnimation animationWithKeyPath:@"position.y"];

springAnimation.mass = 1;

springAnimation.stiffness = 100;

springAnimation.damping = 1;

springAnimation.initialVelocity = 0;

springAnimation.duration = springAnimation.settlingDuration;

springAnimation.fromValue = @(self.opView.center.y);

springAnimation.toValue = @(self.opView.center.y + (btn.selected?+150:-150));

springAnimation.fillMode = kCAFillModeForwards;

[self.opView.layer addAnimation:springAnimation forKey:nil];

btn.selected = !btn.selected;

}

CAKeyframeAnimation關(guān)鍵幀動(dòng)畫

CAKeyframeAnimation的屬性

//關(guān)鍵幀值數(shù)組,一組變化值

@property(nullable, copy) NSArray *values;

//關(guān)鍵幀幀路徑,優(yōu)先級(jí)比values大

@property(nullable) CGPathRef path;

//每一幀對(duì)應(yīng)的時(shí)間,時(shí)間可以控制速度.它和每一個(gè)幀相對(duì)應(yīng),取值為0.0-1.0,不設(shè)則每一幀時(shí)間相等.

@property(nullable, copy) NSArray *keyTimes;

//每一幀對(duì)應(yīng)的時(shí)間曲線函數(shù),也就是每一幀的運(yùn)動(dòng)節(jié)奏

@property(nullable, copy) NSArray *timingFunctions;

//動(dòng)畫的計(jì)算模式,默認(rèn)值: kCAAnimationLinear.有以下幾個(gè)值:

//kCAAnimationLinear//關(guān)鍵幀為座標(biāo)點(diǎn)的時(shí)候,關(guān)鍵幀之間直接直線相連進(jìn)行插值計(jì)算;

//kCAAnimationDiscrete//離散的,也就是沒有補(bǔ)間動(dòng)畫

//kCAAnimationPaced//平均,keyTimes跟timeFunctions失效

//kCAAnimationCubic對(duì)關(guān)鍵幀為座標(biāo)點(diǎn)的關(guān)鍵幀進(jìn)行圓滑曲線相連后插值計(jì)算,對(duì)于曲線的形狀還可以通過tensionValues,continuityValues,biasValues來進(jìn)行調(diào)整自定義,keyTimes跟timeFunctions失效

//kCAAnimationCubicPaced在kCAAnimationCubic的基礎(chǔ)上使得動(dòng)畫運(yùn)行變得均勻,就是系統(tǒng)時(shí)間內(nèi)運(yùn)動(dòng)的距離相同,,keyTimes跟timeFunctions失效

@property(copy) NSString *calculationMode;

//動(dòng)畫的張力,當(dāng)動(dòng)畫為立方計(jì)算模式的時(shí)候此屬性提供了控制插值,因?yàn)槊總€(gè)關(guān)鍵幀都可能有張力所以連續(xù)性會(huì)有所偏差它的范圍為[-1,1].同樣是此作用

@property(nullable, copy) NSArray *tensionValues;

//動(dòng)畫的連續(xù)性值

@property(nullable, copy) NSArray *continuityValues;

//動(dòng)畫的偏斜率

@property(nullable, copy) NSArray *biasValues;

//動(dòng)畫沿路徑旋轉(zhuǎn)方式,默認(rèn)為nil.它有兩個(gè)值:

//kCAAnimationRotateAuto//自動(dòng)旋轉(zhuǎn),

//kCAAnimationRotateAutoReverse//自動(dòng)翻轉(zhuǎn)

@property(nullable, copy) NSString *rotationMode;

CAKeyframeAnimation可以做很豐富的效果,下面展示了幾種純CAKeyframeAnimation做的效果:


實(shí)現(xiàn)代碼:

- (IBAction)animationBegin:(id)sender {

UIButton *btn = (UIButton *)sender;

switch (btn.tag) {

case 0:

case 1:

case 2:

case 3:

case 4:

case 5:

[self path:btn.tag];break;

case 6:

case 7:

[self values:btn.tag];break;

default:

break;

}

}

-(void)path:(NSInteger)tag{

CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];

switch (tag) {

case 0:{

//橢圓

CGMutablePathRef path = CGPathCreateMutable();//創(chuàng)建可變路徑

CGPathAddEllipseInRect(path, NULL, CGRectMake(0, 0, 320, 500));

[animation setPath:path];

CGPathRelease(path);

animation.rotationMode = kCAAnimationRotateAuto;

}break;

case 1:{

//貝塞爾,矩形

UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 320, 320)];

//animation需要的類型是CGPathRef,UIBezierPath是ui的,需要轉(zhuǎn)化成CGPathRef

[animation setPath:path.CGPath];

}break;

case 2:{

//貝塞爾,拋物線

UIBezierPath *path = [UIBezierPath bezierPath];

[path moveToPoint:self.opView.center];

[path addQuadCurveToPoint:CGPointMake(0, 568)

controlPoint:CGPointMake(400, 100)];

[animation setPath:path.CGPath];

}break;

case 3:{

//貝塞爾,s形曲線

UIBezierPath *path = [UIBezierPath bezierPath];

[path moveToPoint:CGPointZero];

[path addCurveToPoint:self.opView.center

controlPoint1:CGPointMake(320, 100)

controlPoint2:CGPointMake(? 0, 400)];

;

[animation setPath:path.CGPath];

}break;

case 4:{

//貝塞爾,圓形

UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:self.view.center

radius:150

startAngle:- M_PI * 0.5

endAngle:M_PI * 2

clockwise:YES];

[animation setPath:path.CGPath];

}break;

case 5:{

CGPoint point = CGPointMake(self.view.center.x, 400);

CGFloat xlength = point.x - self.opView.center.x;

CGFloat ylength = point.y - self.opView.center.y;

CGMutablePathRef path = CGPathCreateMutable();

//移動(dòng)到目標(biāo)點(diǎn)

CGPathMoveToPoint(path, NULL, self.opView.center.x, self.opView.center.y);

//將目標(biāo)點(diǎn)的坐標(biāo)添加到路徑中

CGPathAddLineToPoint(path, NULL, point.x, point.y);

//設(shè)置彈力因子,

CGFloat offsetDivider = 5.0f;

BOOL stopBounciong = NO;

while (stopBounciong == NO) {

CGPathAddLineToPoint(path, NULL, point.x + xlength / offsetDivider, point.y + ylength / offsetDivider);

CGPathAddLineToPoint(path, NULL, point.x, point.y);

offsetDivider += 6.0;

//當(dāng)視圖的當(dāng)前位置距離目標(biāo)點(diǎn)足夠小我們就退出循環(huán)

if ((ABS(xlength / offsetDivider) < 10.0f) && (ABS(ylength / offsetDivider) < 10.0f)) {

break;

}

}

[animation setPath:path];

}break;

default:break;

}

[animation setDuration:0.5];

[animation setRemovedOnCompletion:NO];

[animation setFillMode:kCAFillModeBoth];

[self.opView.layer addAnimation:animation forKey:nil];

}

-(void)values:(NSInteger)tag{

CAKeyframeAnimation *animation = nil;

switch (tag) {

case 6:{

animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];

CGFloat angle = M_PI_4 * 0.5;

NSArray *values = @[@(angle),@(-angle),@(angle)];

[animation setValues:values];

[animation setRepeatCount:3];

[animation setDuration:0.5];

}break;

case 7:{

animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];

NSValue *p1 = [NSValue valueWithCGPoint:self.opView.center];

NSValue *p2 = [NSValue valueWithCGPoint:CGPointMake(self.view.center.x + 100, 200)];

NSValue *p3 = [NSValue valueWithCGPoint:CGPointMake(self.view.center.x, 300)];

//設(shè)置關(guān)鍵幀的值

[animation setValues:@[p1,p2,p3]];

[animation setDuration:0.5];

}break;

default:break;

}

UIGraphicsBeginImageContext(self.view.frame.size);

animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

[animation setRemovedOnCompletion:NO];

[animation setFillMode:kCAFillModeBoth];

[self.opView.layer addAnimation:animation forKey:nil];

}

CAAnimationGroup動(dòng)畫組

CAAnimationGroup的屬性

//只有一個(gè)屬性,數(shù)組中接受CAAnimation元素

@property(nullable, copy) NSArray *animations;

可以看到CAAnimationGroup只有一個(gè)屬性一個(gè)CAAnimation數(shù)組.而且它繼承于CAAnimation,它具有CAAnimation的特性,所以它的用法和CAAnimation是一樣的,不同的是他可以包含n個(gè)動(dòng)畫,也就是說他可以接受很多個(gè)CAAnimation并且可以讓它們一起開始,這就造成了動(dòng)畫效果的疊加,效果就是n個(gè)動(dòng)畫同時(shí)進(jìn)行.

來看一個(gè)簡單的效果:


實(shí)現(xiàn)代碼:

- (IBAction)animationBegin:(id)sender

{

CAAnimationGroup *group = [CAAnimationGroup animation];

/**

*? 移動(dòng)動(dòng)畫

*/

CAKeyframeAnimation *position = [self moveAnimation];

/**

*? 搖晃動(dòng)畫

*/

CAKeyframeAnimation *shake = [self shakeAnimation];

/**

*? 透明度動(dòng)畫

*/

CABasicAnimation *alpha = [self alphaAnimation];

/**

*? 設(shè)置動(dòng)畫組的時(shí)間,這個(gè)時(shí)間表示動(dòng)畫組的總時(shí)間,它的子動(dòng)畫的時(shí)間和這個(gè)時(shí)間沒有關(guān)系

*/

[group setDuration:3.0];

[group setAnimations:@[position,shake,alpha]];

[self.opView.layer addAnimation:group forKey:nil];

}

#pragma mark -- CAKeyframeAnimation - 路徑平移動(dòng)畫

-(CAKeyframeAnimation *)moveAnimation

{

CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];

/**

*? 設(shè)置路徑,按圓運(yùn)動(dòng)

*/

CGMutablePathRef path = CGPathCreateMutable();//CG是C語言的框架,需要直接寫語法

CGPathAddEllipseInRect(path, NULL, CGRectMake(0, 0, 320, 320));

[animation setPath:path];//把路徑給動(dòng)畫

CGPathRelease(path);//釋放路徑

/**

*? 設(shè)置動(dòng)畫時(shí)間,這是動(dòng)畫總時(shí)間,不是每一幀的時(shí)間

*/

[animation setDuration:3];

/**

*setRemovedOnCompletion 設(shè)置動(dòng)畫完成后是否將圖層移除掉,默認(rèn)是移除

*setFillMode 當(dāng)前設(shè)置的是向前填充,意味著動(dòng)畫完成后填充效果為最新的效果,此屬性有效的前提是 setRemovedOnCompletion=NO

*注意:

*1.動(dòng)畫只是改變?nèi)说囊曈X,它并不會(huì)改變視圖的初始位置等信息,也就是說無論動(dòng)畫怎么東,都不會(huì)改變view的原始大小,只是看起來像是大小改變了而已

*2.因?yàn)闆]有改變視圖的根本大小,所以視圖所接收事件的位置還是原來的大小,可以不是顯示的大小

*/

[animation setRemovedOnCompletion:NO];

[animation setFillMode:kCAFillModeForwards];

return animation;

}

#pragma mark -- CAKeyframeAnimation - 搖晃動(dòng)畫

-(CAKeyframeAnimation *)shakeAnimation

{

CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];

/**

*? 設(shè)置路徑,貝塞爾路徑

*/

CGFloat angle = M_PI_4 * 0.1;

NSArray *values = @[@(angle),@(-angle),@(angle)];

[animation setValues:values];

[animation setRepeatCount:10];

/**

*? 設(shè)置動(dòng)畫時(shí)間,這是動(dòng)畫總時(shí)間,不是每一幀的時(shí)間

*/

[animation setDuration:0.25];

return animation;

}

#pragma mark -- CABasicAnimation - 淡如淡出動(dòng)畫

-(CABasicAnimation *)alphaAnimation

{

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];

[animation setDuration:1.0];

/**

* 設(shè)置重復(fù)次數(shù)

*/

[animation setRepeatCount:3];

/**

* 設(shè)置自動(dòng)翻轉(zhuǎn)

* 設(shè)置自動(dòng)翻轉(zhuǎn)以后單次動(dòng)畫時(shí)間不變,總動(dòng)畫時(shí)間延遲一倍,它會(huì)讓你前半部分的動(dòng)畫以相反的方式動(dòng)畫過來

* 比如說你設(shè)置執(zhí)行一次動(dòng)畫,從a到b時(shí)間為1秒,設(shè)置自動(dòng)翻轉(zhuǎn)以后動(dòng)畫的執(zhí)行方式為,先從a到b執(zhí)行一秒,然后從b到a再執(zhí)行一下動(dòng)畫結(jié)束

*/

[animation setAutoreverses:YES];

/**

* 設(shè)置起始值

*/

[animation setFromValue:@1.0];

/**

* 設(shè)置目標(biāo)值

*/

[animation setToValue:@0.1];

/**

* 將動(dòng)畫添加到layer 添加到圖層開始執(zhí)行動(dòng)畫,

* 注意:key值的設(shè)置與否會(huì)影響動(dòng)畫的效果

* 如果不設(shè)置key值每次執(zhí)行都會(huì)創(chuàng)建一個(gè)動(dòng)畫,然后創(chuàng)建的動(dòng)畫會(huì)疊加在圖層上

* 如果設(shè)置key值,系統(tǒng)執(zhí)行這個(gè)動(dòng)畫時(shí)會(huì)先檢查這個(gè)動(dòng)畫有沒有被創(chuàng)建,如果沒有的話就創(chuàng)建一個(gè),如果有的話就重新從頭開始執(zhí)行這個(gè)動(dòng)畫

* 你可以通過key值獲取或者刪除一個(gè)動(dòng)畫

*/

return animation;

}

CATransition轉(zhuǎn)場(chǎng)動(dòng)畫

CATransition屬性

//轉(zhuǎn)場(chǎng)類型,字符串類型參數(shù).系統(tǒng)提供了四中動(dòng)畫形式:

//kCATransitionFade//逐漸消失

//kCATransitionMoveIn//移進(jìn)來

//kCATransitionPush//推進(jìn)來

//kCATransitionReveal//揭開

//另外,除了系統(tǒng)給的這幾種動(dòng)畫效果,我們還可以使用系統(tǒng)私有的動(dòng)畫效果:

//@"cube",//立方體翻轉(zhuǎn)效果

//@"oglFlip",//翻轉(zhuǎn)效果

//@"suckEffect",//收縮效果,動(dòng)畫方向不可控

//@"rippleEffect",//水滴波紋效果,動(dòng)畫方向不可控

//@"pageCurl",//向上翻頁效果

//@"pageUnCurl",//向下翻頁效果

//@"cameralIrisHollowOpen",//攝像頭打開效果,動(dòng)畫方向不可控

//@"cameraIrisHollowClose",//攝像頭關(guān)閉效果,動(dòng)畫方向不可控

@property(copy) NSString *type;

//轉(zhuǎn)場(chǎng)方向,系統(tǒng)一共提供四個(gè)方向:

//kCATransitionFromRight//從右開始

//kCATransitionFromLeft//從左開始

//kCATransitionFromTop//從上開始

//kCATransitionFromBottom//從下開始

@property(nullable, copy) NSString *subtype;

//開始進(jìn)度,默認(rèn)0.0.如果設(shè)置0.3,那么動(dòng)畫將從動(dòng)畫的0.3的部分開始

@property float startProgress;

//結(jié)束進(jìn)度,默認(rèn)1.0.如果設(shè)置0.6,那么動(dòng)畫將從動(dòng)畫的0.6部分以后就會(huì)結(jié)束

@property float endProgress;

//開始進(jìn)度

@property(nullable, strong) id filter;

CATransition也是繼承CAAnimation,系統(tǒng)默認(rèn)提供了12種動(dòng)畫樣式,加上4個(gè)動(dòng)畫方向,除了方向不可控的四種效果外,大概一共提供了36種動(dòng)畫.

另外系統(tǒng)還給UIView添加了很多分類方法可以快速完成一些簡單的動(dòng)畫,如下:

UIView(UIViewAnimation)

@interface UIView(UIViewAnimation)

+ (void)beginAnimations:(nullable NSString *)animationID context:(nullable void *)context;? // additional context info passed to will start/did stop selectors. begin/commit can be nested

//提交動(dòng)畫

+ (void)commitAnimations;

//設(shè)置代理

+ (void)setAnimationDelegate:(nullable id)delegate;? ? ? ? ? ? ? ? ? ? ? ? ? //設(shè)置動(dòng)畫開始方法

+ (void)setAnimationWillStartSelector:(nullable SEL)selector;

//設(shè)置動(dòng)畫結(jié)束方法

+ (void)setAnimationDidStopSelector:(nullable SEL)selector;

//設(shè)置動(dòng)畫時(shí)間:default = 0.2

+ (void)setAnimationDuration:(NSTimeInterval)duration;

//設(shè)置動(dòng)畫延遲開始時(shí)間:default = 0.0

+ (void)setAnimationDelay:(NSTimeInterval)delay;

//設(shè)置動(dòng)畫延遲開始日期:default = now ([NSDate date])

+ (void)setAnimationStartDate:(NSDate *)startDate;

//設(shè)置動(dòng)畫運(yùn)動(dòng)曲線:default =UIViewAnimationCurveEaseInOut

//UIViewAnimationCurveEaseInOut,//慢進(jìn)慢出

//UIViewAnimationCurveEaseIn, //慢進(jìn)快出

//UIViewAnimationCurveEaseOut,//快進(jìn)慢出

//UIViewAnimationCurveLinear//勻速

+ (void)setAnimationCurve:(UIViewAnimationCurve)curve;

//設(shè)置重復(fù)次數(shù): default = 0.0.? May be fractional

+ (void)setAnimationRepeatCount:(float)repeatCount;

//設(shè)置是否翻轉(zhuǎn)動(dòng)畫: default = NO. used if repeat

+ (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses;

//設(shè)置動(dòng)畫是否從當(dāng)前狀態(tài)開始:default = NO

+ (void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState;

//設(shè)置動(dòng)畫類型

+ (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache;

//設(shè)置動(dòng)畫是否有效

+ (void)setAnimationsEnabled:(BOOL)enabled;

//

+ (BOOL)areAnimationsEnabled;

//

+ (void)performWithoutAnimation:(void (^)(void))actionsWithoutAnimation

//

+ (NSTimeInterval)inheritedAnimationDuration

@end

UIView(UIViewAnimationWithBlocks)

@interface UIView(UIViewAnimationWithBlocks)

//以下方法都大同小異,就不一一做注釋了

+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion;

+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion

+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations;

+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion

+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))animations completion:(void (^ __nullable)(BOOL finished))completion;

+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^ __nullable)(BOOL finished))completion;

+ (void)performSystemAnimation:(UISystemAnimation)animation onViews:(NSArray *)views options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))parallelAnimations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);

@end

UIView (UIViewKeyframeAnimations)

+ (void)animateKeyframesWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewKeyframeAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion;

+ (void)addKeyframeWithRelativeStartTime:(double)frameStartTime relativeDuration:(double)frameDuration animations:(void (^)(void))animations

以上方法比較多,找值得說的簡單說一下吧:

//單視圖轉(zhuǎn)場(chǎng)動(dòng)畫

+ (void)transitionWithView:(UIView *)view

duration:(NSTimeInterval)duration

options:(UIViewAnimationOptions)options

animations:(void (^ __nullable)(void))animations

completion:(void (^ __nullable)(BOOL finished))completion

//雙視圖轉(zhuǎn)場(chǎng)動(dòng)畫

+ (void)transitionFromView:(UIView *)fromView

toView:(UIView *)toView

duration:(NSTimeInterval)duration

options:(UIViewAnimationOptions)options

completion:(void (^ __nullable)(BOOL finished))completion

這兩個(gè)都是轉(zhuǎn)場(chǎng)動(dòng)畫,不同的是第一個(gè)是單視圖轉(zhuǎn)場(chǎng),第二個(gè)是雙視圖轉(zhuǎn)場(chǎng).不過需要注意的是:單視圖轉(zhuǎn)場(chǎng)動(dòng)畫只能用作屬性動(dòng)畫做不到的轉(zhuǎn)場(chǎng)效果,比如屬性動(dòng)畫不能給UIImageview的image賦值操作做動(dòng)畫效果等.

我們可以看到以上兩個(gè)方法中都有一個(gè)共同的參數(shù):

UIViewAnimationOptions

typedef NS_OPTIONS(NSUInteger, UIViewAnimationOptions) {

UIViewAnimationOptionLayoutSubviews? ? ? ? ? ? = 1 <<? 0,

UIViewAnimationOptionAllowUserInteraction? ? ? = 1 <<? 1, // turn on user interaction while animating

UIViewAnimationOptionBeginFromCurrentState? ? = 1 <<? 2, // start all views from current value, not initial value

UIViewAnimationOptionRepeat? ? ? ? ? ? ? ? ? ? = 1 <<? 3, // repeat animation indefinitely

UIViewAnimationOptionAutoreverse? ? ? ? ? ? ? = 1 <<? 4, // if repeat, run animation back and forth

UIViewAnimationOptionOverrideInheritedDuration = 1 <<? 5, // ignore nested duration

UIViewAnimationOptionOverrideInheritedCurve? ? = 1 <<? 6, // ignore nested curve

UIViewAnimationOptionAllowAnimatedContent? ? ? = 1 <<? 7, // animate contents (applies to transitions only)

UIViewAnimationOptionShowHideTransitionViews? = 1 <<? 8, // flip to/from hidden state instead of adding/removing

UIViewAnimationOptionOverrideInheritedOptions? = 1 <<? 9, // do not inherit any options or animation type

UIViewAnimationOptionCurveEaseInOut? ? ? ? ? ? = 0 << 16, // default

UIViewAnimationOptionCurveEaseIn? ? ? ? ? ? ? = 1 << 16,

UIViewAnimationOptionCurveEaseOut? ? ? ? ? ? ? = 2 << 16,

UIViewAnimationOptionCurveLinear? ? ? ? ? ? ? = 3 << 16,

UIViewAnimationOptionTransitionNone? ? ? ? ? ? = 0 << 20, // default

UIViewAnimationOptionTransitionFlipFromLeft? ? = 1 << 20,

UIViewAnimationOptionTransitionFlipFromRight? = 2 << 20,

UIViewAnimationOptionTransitionCurlUp? ? ? ? ? = 3 << 20,

UIViewAnimationOptionTransitionCurlDown? ? ? ? = 4 << 20,

UIViewAnimationOptionTransitionCrossDissolve? = 5 << 20,

UIViewAnimationOptionTransitionFlipFromTop? ? = 6 << 20,

UIViewAnimationOptionTransitionFlipFromBottom? = 7 << 20,

} NS_ENUM_AVAILABLE_IOS(4_0);

可以看到系統(tǒng)給到的是一個(gè)位移枚舉,這就意味著這個(gè)枚舉可以多個(gè)值同時(shí)使用,但是怎么用呢?其實(shí)那些枚舉值可以分為三個(gè)部分.

我們分別看一下每個(gè)枚舉的意思:

第一部分:動(dòng)畫效果

UIViewAnimationOptionTransitionNone//沒有效果

UIViewAnimationOptionTransitionFlipFromLeft//從左水平翻轉(zhuǎn)

UIViewAnimationOptionTransitionFlipFromRight//從右水平翻轉(zhuǎn)

UIViewAnimationOptionTransitionCurlUp//翻書上掀

UIViewAnimationOptionTransitionCurlDown//翻書下蓋UIViewAnimationOptionTransitionCrossDissolve//融合

UIViewAnimationOptionTransitionFlipFromTop//從上垂直翻轉(zhuǎn)

UIViewAnimationOptionTransitionFlipFromBottom//從下垂直翻轉(zhuǎn)

第二部分:動(dòng)畫運(yùn)動(dòng)曲線

//開始慢,加速到中間,然后減慢到結(jié)束

UIViewAnimationOptionCurveEaseInOut

//開始慢,加速到結(jié)束

UIViewAnimationOptionCurveEaseIn

//開始快,減速到結(jié)束

UIViewAnimationOptionCurveEaseOut

//線性運(yùn)動(dòng)

UIViewAnimationOptionCurveLinear

第三部分:其他

//默認(rèn),跟父類作為一個(gè)整體

UIViewAnimationOptionLayoutSubviews

//設(shè)置了這個(gè),主線程可以接收點(diǎn)擊事件

UIViewAnimationOptionAllowUserInteraction

//從當(dāng)前狀態(tài)開始動(dòng)畫,父層動(dòng)畫運(yùn)動(dòng)期間,開始子層動(dòng)畫.

UIViewAnimationOptionBeginFromCurrentState

//重復(fù)執(zhí)行動(dòng)畫,從開始到結(jié)束, 結(jié)束后直接跳到開始態(tài)

UIViewAnimationOptionRepeat

//反向執(zhí)行動(dòng)畫,結(jié)束后會(huì)再從結(jié)束態(tài)->開始態(tài)

UIViewAnimationOptionAutoreverse

//忽略繼承自父層持續(xù)時(shí)間,使用自己持續(xù)時(shí)間(如果存在)

UIViewAnimationOptionOverrideInheritedDuration

//忽略繼承自父層的線性效果,使用自己的線性效果(如果存在)

UIViewAnimationOptionOverrideInheritedCurve

//允許同一個(gè)view的多個(gè)動(dòng)畫同時(shí)進(jìn)行

UIViewAnimationOptionAllowAnimatedContent

//視圖切換時(shí)直接隱藏舊視圖、顯示新視圖,而不是將舊視圖從父視圖移除(僅僅適用于轉(zhuǎn)場(chǎng)動(dòng)畫)? ? ? ? ? ? UIViewAnimationOptionShowHideTransitionViews

//不繼承父動(dòng)畫設(shè)置或動(dòng)畫類型.

UIViewAnimationOptionOverrideInheritedOptions

這下可以看到,這些枚舉功能都不一樣但是可以隨意組合,但是組合的時(shí)候需要注意,同一類型的枚舉不能一起使用比如UIViewAnimationOptionCurveEaseIn和UIViewAnimationOptionCurveEaseOut

然后我們看一下轉(zhuǎn)場(chǎng)動(dòng)畫的一些效果:

單視圖轉(zhuǎn)場(chǎng)


單視圖轉(zhuǎn)場(chǎng).gif

雙視圖轉(zhuǎn)場(chǎng)


雙視圖轉(zhuǎn)場(chǎng).gif

CATransition轉(zhuǎn)場(chǎng)


CATransition轉(zhuǎn)場(chǎng).gif

實(shí)現(xiàn)代碼:

- (IBAction)animationBegin:(id)sender

{

UIButton *btn = (UIButton *)sender;

switch (btn.tag)

{

case 0:

[self animationSingleView:YES];

break;

case 1:

[self animationSingleView:NO];

break;

case 2:[self chang3];

break;

default:break;

}

}

/**

*? 轉(zhuǎn)場(chǎng)動(dòng)畫在執(zhí)行過程中不可以被停止,

*? 轉(zhuǎn)場(chǎng)動(dòng)畫在執(zhí)行過程中不可以用戶交互

*? 轉(zhuǎn)場(chǎng)動(dòng)畫在執(zhí)行過程中不可以控制動(dòng)畫執(zhí)行進(jìn)度

*/

/**

*? 基于UIView的單視圖轉(zhuǎn)場(chǎng)動(dòng)畫

*/

static NSUInteger change1_0Index = 0;

static NSUInteger change1_1Index = 0;

static NSUInteger change1_2Index = 0;

-(void)animationSingleView:(BOOL)sigle

{

/**

*? 第一部分

*/

NSArray *array0 = @[

@(UIViewAnimationOptionTransitionNone),

@(UIViewAnimationOptionTransitionFlipFromLeft),//從左水平翻轉(zhuǎn)

@(UIViewAnimationOptionTransitionFlipFromRight),//從右水平翻轉(zhuǎn)

@(UIViewAnimationOptionTransitionCurlUp),//翻書上掀

@(UIViewAnimationOptionTransitionCurlDown),//翻書下蓋

@(UIViewAnimationOptionTransitionCrossDissolve),//融合

@(UIViewAnimationOptionTransitionFlipFromTop),//從上垂直翻轉(zhuǎn)

@(UIViewAnimationOptionTransitionFlipFromBottom),//從下垂直翻轉(zhuǎn)

];

/**

*? 第二部分

*/

NSArray *array1 = @[

@(UIViewAnimationOptionCurveEaseInOut),////開始慢,加速到中間,然后減慢到結(jié)束

@(UIViewAnimationOptionCurveEaseIn),//開始慢,加速到結(jié)束

@(UIViewAnimationOptionCurveEaseOut),//開始快,減速到結(jié)束

@(UIViewAnimationOptionCurveLinear),//線性運(yùn)動(dòng)

];

/**

*? 第三部分

*/

NSArray *array2 = @[

@(UIViewAnimationOptionLayoutSubviews),//默認(rèn),跟父類作為一個(gè)整體

@(UIViewAnimationOptionAllowUserInteraction),//設(shè)置了這個(gè),主線程可以接收點(diǎn)擊事件

@(UIViewAnimationOptionBeginFromCurrentState),//從當(dāng)前狀態(tài)開始動(dòng)畫,父層動(dòng)畫運(yùn)動(dòng)期間,開始子層動(dòng)畫。

@(UIViewAnimationOptionRepeat),//重復(fù)執(zhí)行動(dòng)畫,從開始到結(jié)束, 結(jié)束后直接跳到開始態(tài)

@(UIViewAnimationOptionAutoreverse),//反向執(zhí)行動(dòng)畫,結(jié)束后會(huì)再從結(jié)束態(tài)->開始態(tài)

@(UIViewAnimationOptionOverrideInheritedDuration),//忽略繼承自父層持續(xù)時(shí)間,使用自己持續(xù)時(shí)間(如果存在)

@(UIViewAnimationOptionOverrideInheritedCurve),//忽略繼承自父層的線性效果,使用自己的線性效果(如果存在)

@(UIViewAnimationOptionAllowAnimatedContent),//允許同一個(gè)view的多個(gè)動(dòng)畫同時(shí)進(jìn)行

@(UIViewAnimationOptionShowHideTransitionViews),//視圖切換時(shí)直接隱藏舊視圖、顯示新視圖,而不是將舊視圖從父視圖移除(僅僅適用于轉(zhuǎn)場(chǎng)動(dòng)畫)

@(UIViewAnimationOptionOverrideInheritedOptions),//不繼承父動(dòng)畫設(shè)置或動(dòng)畫類型。

];

//? ? CASpringAnimation

//? ? CASpringAnimation

if (sigle)

{

[UIView transitionWithView:self.opView1

duration:1

options:

((NSNumber *)array0[change1_0Index]).integerValue|

((NSNumber *)array1[change1_1Index]).integerValue|

((NSNumber *)array2[change1_2Index]).integerValue

animations:^{

/**

*? 單視圖的轉(zhuǎn)場(chǎng)動(dòng)畫需要在動(dòng)畫塊中設(shè)置視圖轉(zhuǎn)場(chǎng)前的內(nèi)容和視圖轉(zhuǎn)場(chǎng)后的內(nèi)容

*/

if (self.opView1.tag == 0)

{

self.opView1.image = [UIImage imageNamed:@"IMG_1730"];

self.opView1.tag = 1;

}

else

{

self.opView1.image = [UIImage imageNamed:@"93F5E460-9D31-4780-8511-37FF91033402"];

self.opView1.tag = 0;

}

} completion:nil];

NSLog(@"動(dòng)畫:%s:%@:%@:%@",__func__,@(change1_0Index),@(change1_1Index),@(change1_2Index));

}

else

{

/**

*? 雙視圖的轉(zhuǎn)場(chǎng)動(dòng)畫

*? 注意:雙視圖的轉(zhuǎn)場(chǎng)動(dòng)畫實(shí)際上是操作視圖移除和添加到父視圖的一個(gè)過程,from視圖必須要有父視圖,to視圖必須不能有父視圖,否則會(huì)出問題

*? 比如動(dòng)畫不準(zhǔn)等

*/

UIImageView *fromView = nil;

UIImageView *toView = nil;

if (self.opView1.tag == 0)

{

fromView = self.opView1;

toView = self.opView2;

self.opView1.tag = 1;

}

else

{

fromView = self.opView2;

toView = self.opView1;

self.opView1.tag = 0;

}

[UIView transitionFromView:fromView

toView:toView duration:1.0

options:

((NSNumber *)array0[change1_0Index]).integerValue|

((NSNumber *)array1[change1_1Index]).integerValue|

((NSNumber *)array2[change1_2Index]).integerValue

completion:^(BOOL finished) {

[fromView removeFromSuperview];

}];

[self.view addSubview:toView];

}

change1_0Index += 1;

if (change1_0Index > array0.count - 1)

{

change1_0Index = 0;

change1_1Index += 1;

}

if (change1_1Index > array1.count - 1)

{

change1_1Index = 0;

change1_2Index += 1;

}

if (change1_2Index > array2.count - 1)

{

change1_2Index = 0;

change1_0Index = 0;

change1_2Index = 0;

}

}

/**

*? 基于CATransition的視圖轉(zhuǎn)場(chǎng)動(dòng)畫

*/

static NSUInteger change3_0Index = 0;

static NSUInteger change3_1Index = 0;

-(void)chang3

{

/**

*創(chuàng)建轉(zhuǎn)場(chǎng)動(dòng)畫:注意:CATransaction和CATransition 不一樣

*/

CATransition *transition = [CATransition animation];

transition.duration = 0.25;

NSArray *type_array = @[

//系統(tǒng)提供的動(dòng)畫

kCATransitionFade,

kCATransitionMoveIn,

kCATransitionPush,

kCATransitionReveal,

//以下是私有api,只能字符串訪問

@"cube",//立方體翻轉(zhuǎn)效果

@"oglFlip",//翻轉(zhuǎn)效果

@"suckEffect",//收縮效果,動(dòng)畫方向不可控

@"rippleEffect",//水滴波紋效果,動(dòng)畫方向不可控

@"pageCurl",//向上翻頁效果

@"pageUnCurl",//向下翻頁效果

@"cameralIrisHollowOpen",//攝像頭打開效果,動(dòng)畫方向不可控

@"cameraIrisHollowClose",//攝像頭關(guān)閉效果,動(dòng)畫方向不可控

];

//轉(zhuǎn)場(chǎng)類型

transition.type = type_array[change3_0Index];

NSArray *subtype_array = @[

kCATransitionFromRight,

kCATransitionFromLeft,

kCATransitionFromTop,

kCATransitionFromBottom

];

//轉(zhuǎn)場(chǎng)方向

transition.subtype = subtype_array[change3_1Index];

/**

*? 設(shè)置轉(zhuǎn)場(chǎng)動(dòng)畫的開始和結(jié)束百分比

*/

transition.startProgress = 0.0;

transition.endProgress = 1.0;

if (self.opView1.tag == 0)

{

self.opView1.tag = 1;

self.opView1.image = [UIImage imageNamed:@"IMG_1730"];

self.opView2.image = [UIImage imageNamed:@"93F5E460-9D31-4780-8511-37FF91033402"];

}

else

{

self.opView1.tag = 0;

self.opView1.image = [UIImage imageNamed:@"93F5E460-9D31-4780-8511-37FF91033402"];

self.opView2.image = [UIImage imageNamed:@"IMG_1730"];

}

[self.opView1.layer addAnimation:transition forKey:nil];

[self.opView2.layer addAnimation:transition forKey:nil];

NSLog(@"動(dòng)畫:%s:%@:%@",__func__,@(change3_0Index),@(change3_1Index));

change3_1Index += 1;

if (change3_1Index > subtype_array.count - 1)

{

change3_1Index = 0;

change3_0Index += 1;

}

if (change3_0Index > type_array.count - 1)

{

change3_0Index = 0;

}

}

作者:xqqlv

鏈接:http://www.itdecent.cn/p/4c3bace804e3

來源:簡書

著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在iOS實(shí)際開發(fā)中常用的動(dòng)畫無非是以下四種:UIView動(dòng)畫,核心動(dòng)畫,幀動(dòng)畫,自定義轉(zhuǎn)場(chǎng)動(dòng)畫。 1.UIView...
    請(qǐng)叫我周小帥閱讀 3,333評(píng)論 1 23
  • 動(dòng)畫的繼承結(jié)構(gòu) CAAnimation{CAPropertyAnimation{CABasicAnimation{...
    早起的蟲兒子被鳥吃閱讀 960評(píng)論 0 1
  • 在iOS中隨處都可以看到絢麗的動(dòng)畫效果,實(shí)現(xiàn)這些動(dòng)畫的過程并不復(fù)雜,今天將帶大家一窺ios動(dòng)畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,698評(píng)論 6 30
  • 在iOS中隨處都可以看到絢麗的動(dòng)畫效果,實(shí)現(xiàn)這些動(dòng)畫的過程并不復(fù)雜,今天將帶大家一窺iOS動(dòng)畫全貌。在這里你可以看...
    F麥子閱讀 5,273評(píng)論 5 13
  • Core Animation Core Animation,中文翻譯為核心動(dòng)畫,它是一組非常強(qiáng)大的動(dòng)畫處理API,...
    45b645c5912e閱讀 3,164評(píng)論 0 21

友情鏈接更多精彩內(nèi)容