先看看CAAnimation動(dòng)畫(huà)的繼承結(jié)構(gòu)
CAAnimation{
CAPropertyAnimation {
CABasicAnimation {
CASpringAnimation
}
CAKeyframeAnimation
}
CATransition
CAAnimationGroup
}
CAAnimation基本屬性詳解
//動(dòng)畫(huà)的動(dòng)作規(guī)則,包含以下值
//kCAMediaTimingFunctionLinear 勻速
//kCAMediaTimingFunctionEaseIn 慢進(jìn)快出
//kCAMediaTimingFunctionEaseOut 快進(jìn)慢出
//kCAMediaTimingFunctionEaseInEaseOut 慢進(jìn)慢出 中間加速
//kCAMediaTimingFunctionDefault 默認(rèn)
@property(nullable, strong) CAMediaTimingFunction *timingFunction;
//動(dòng)畫(huà)的代理回調(diào)
@property(nullable, strong) id <CAAnimationDelegate> delegate;
//動(dòng)畫(huà)執(zhí)行完以后是否移除動(dòng)畫(huà),默認(rèn)YES
@property(getter=isRemovedOnCompletion) BOOL removedOnCompletion;
以上屬性詳解:
- delegate:動(dòng)畫(huà)執(zhí)行的代理,在動(dòng)畫(huà)開(kāi)始前設(shè)定,不用顯式的寫(xiě)在代碼里,它包含兩個(gè)方法:
動(dòng)畫(huà)開(kāi)始回調(diào)
- (void)animationDidStart:(CAAnimation *)aim;
動(dòng)畫(huà)結(jié)束回調(diào)
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
- removedOnCompletion:動(dòng)畫(huà)完成后是否移除動(dòng)畫(huà).默認(rèn)為YES.此屬性為YES時(shí), fillMode不可用,具體為什么不可用,可以自己結(jié)合兩個(gè)屬性分析一下,這里不再贅述.
- timingFunction 設(shè)置動(dòng)畫(huà)速度曲線,默認(rèn)值上面已經(jīng)給出.下面說(shuō)它的幾個(gè)方法:
這兩個(gè)方法是一樣的.如果我們對(duì)系統(tǒng)自帶的速度函數(shù)不滿意,可以通過(guò)這兩個(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)畫(huà)高級(jí)編程/10-緩沖
- (void)getControlPointAtIndex:(size_t)idx values:(float[2])ptr;
CAAnimation協(xié)議的屬性
//開(kāi)始時(shí)間.這個(gè)屬性比較復(fù)雜,傻瓜用法為:CACurrentMediaTime() + x,
//其中x為延遲時(shí)間.如果設(shè)置 beginTime = CACurrentMediaTime() + 1.0,產(chǎn)生的效果為延遲一秒執(zhí)行動(dòng)畫(huà),下面詳解原理
@property CFTimeInterval beginTime;
//動(dòng)畫(huà)執(zhí)行時(shí)間,此屬性和speed有關(guān)系speed默認(rèn)為1.0,如果speed設(shè)置為2.0,那么動(dòng)畫(huà)執(zhí)行時(shí)間則為duration*(1.0/2.0).
@property CFTimeInterval duration;
//動(dòng)畫(huà)執(zhí)行速度,它duration的關(guān)系參考上面解釋
@property float speed;
//動(dòng)畫(huà)的時(shí)間延遲,這個(gè)屬性比較復(fù)雜,下面詳解
@property CFTimeInterval timeOffset;
//重復(fù)執(zhí)行次數(shù)
@property float repeatCount;
//重復(fù)執(zhí)行時(shí)間,此屬性?xún)?yōu)先級(jí)大于repeatCount.也就是說(shuō)如果repeatDuration設(shè)置為1秒重復(fù)10次,那么它會(huì)在1秒內(nèi)執(zhí)行完動(dòng)畫(huà).
@property CFTimeInterval repeatDuration;
//是否自動(dòng)翻轉(zhuǎn)動(dòng)畫(huà),默認(rèn)NO.如果設(shè)置YES,那么整個(gè)動(dòng)畫(huà)的執(zhí)行效果為A->B->A.
@property BOOL autoreverses;
//動(dòng)畫(huà)的填充方式,默認(rèn)為: kCAFillModeRemoved,包含以下值
//kCAFillModeForwards//動(dòng)畫(huà)結(jié)束后回到準(zhǔn)備狀態(tài)
//kCAFillModeBackwards//動(dòng)畫(huà)結(jié)束后保持最后狀態(tài)
//kCAFillModeBoth//動(dòng)畫(huà)結(jié)束后回到準(zhǔn)備狀態(tài),并保持最后狀態(tài)
//kCAFillModeRemoved//執(zhí)行完成移除動(dòng)畫(huà)
@property(copy) NSString *fillMode;
以上屬性的詳解:
- beginTime:剛才上面簡(jiǎn)單解釋了下這個(gè)屬性的用法:CACurrentMediaTime()+ x 會(huì)使動(dòng)畫(huà)延遲執(zhí)行x秒.不知道到這里有沒(méi)有人想過(guò)如果-x會(huì)出現(xiàn)怎么樣效果?假設(shè)我們有執(zhí)行一個(gè)3秒的動(dòng)畫(huà),然后設(shè)置beginTime = CACurrentMediaTime()- 1.5那么執(zhí)行動(dòng)畫(huà)你會(huì)發(fā)現(xiàn)動(dòng)畫(huà)只會(huì)執(zhí)行后半段,也就是只執(zhí)行后面的3-1.5s的動(dòng)畫(huà).為什么會(huì)這樣?其實(shí)動(dòng)畫(huà)都有一個(gè)timeline(時(shí)間線)的概念.動(dòng)畫(huà)開(kāi)始執(zhí)行都是基于這個(gè)時(shí)間線的絕對(duì)時(shí)間,這個(gè)時(shí)間和它的父類(lèi)有關(guān)(系統(tǒng)的屬性注釋可以看到).默認(rèn)的CALayer的beginTime為零,如果這個(gè)值為零的話,系統(tǒng)會(huì)把它設(shè)置為CACurrentMediaTime(),那么這個(gè)時(shí)間就是正常執(zhí)行動(dòng)畫(huà)的時(shí)間:立即執(zhí)行.所以如果你設(shè)置beginTime=CACurrentMediaTime()+x;它會(huì)把它的執(zhí)行時(shí)間線推遲x秒,也就是晚執(zhí)行x秒,如果你beginTime=CACurrentMediaTime()-x;那它開(kāi)始的時(shí)候會(huì)從你動(dòng)畫(huà)對(duì)應(yīng)的絕對(duì)時(shí)間開(kāi)始執(zhí)行.
- timeOffset:時(shí)間偏移量,默認(rèn)為0;既然它是時(shí)間偏移量,那么它即和動(dòng)畫(huà)時(shí)間相關(guān).這么解釋:假設(shè)我們?cè)O(shè)置一個(gè)動(dòng)畫(huà)時(shí)間為5s,動(dòng)畫(huà)執(zhí)行的過(guò)程為1->2->3->4->5,這時(shí)候如果你設(shè)置timeOffset = 2s那么它的執(zhí)行過(guò)程就會(huì)變成3->4->5->1->2如果你設(shè)置timeOffset = 4s那么它的執(zhí)行過(guò)程就會(huì)變成5->1->2->3->4,這么說(shuō)應(yīng)該很明白了吧?
CAPropertyAnimation的基本屬性
//需要?jiǎng)赢?huà)的屬性值
@property(nullable, copy) NSString *keyPath;
//屬性動(dòng)畫(huà)是否以當(dāng)前動(dòng)畫(huà)效果為基礎(chǔ),默認(rèn)為NO
@property(getter=isAdditive) BOOL additive;
//指定動(dòng)畫(huà)是否為累加效果,默認(rèn)為NO
@property(getter=isCumulative) BOOL cumulative;
//此屬性相當(dāng)于CALayer中的transform屬性,下面會(huì)詳解
@property(nullable, strong) CAValueFunction *valueFunction;
以上屬性的詳解:
CAPropertyAnimation是屬性動(dòng)畫(huà).顧名思義也就是針對(duì)屬性才可以做的動(dòng)畫(huà).那它可以對(duì)誰(shuí)的屬性可以做動(dòng)畫(huà)?是CALayer的屬性,比如:bounds,position等.那么問(wèn)題來(lái)了,我們改變CALayer的position可以直接設(shè)置[CAPropertyAnimation animationWithKeyPath:@"position"]如果我們?cè)O(shè)置它的transform(CATransform3D)呢?CATransform3D是一個(gè)矩陣,如果我們想為它做動(dòng)畫(huà)怎么辦?下面這個(gè)屬性就是用來(lái)解決這個(gè)問(wèn)題的.
- valueFunction:我們來(lái)看它可以設(shè)置的值:
kCAValueFunctionRotateX
kCAValueFunctionRotateY
kCAValueFunctionRotateZ
kCAValueFunctionScale
kCAValueFunctionScaleX
kCAValueFunctionScaleY
kCAValueFunctionScaleZ
kCAValueFunctionTranslate
kCAValueFunctionTranslateX
kCAValueFunctionTranslateY
kCAValueFunctionTranslateZ```
CAPropertyAnimation的方法
//通過(guò)key創(chuàng)建一個(gè)CAPropertyAnimation對(duì)象
- (instancetype)animationWithKeyPath:(nullable NSString *)path;
下面我們來(lái)看一下可以設(shè)置屬性動(dòng)畫(huà)的屬性歸總:
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**是基類(lèi),* *CAPropertyAnimation**是抽象類(lèi),兩者都不可以直接使用, 那我們只有使用它的子類(lèi)了.
## CABasicAnimation基本動(dòng)畫(huà)
### CABasicAnimation的屬性
//開(kāi)始值
@property(nullable, strong) id fromValue;
//結(jié)束值
@property(nullable, strong) id toValue;
//結(jié)束值
@property(nullable, strong) id byValue;
這三個(gè)屬性之間的規(guī)則
* fromValue和toValue不為空,動(dòng)畫(huà)的效果會(huì)從fromValue的值變化到toValue.
* fromValue和byValue都不為空,動(dòng)畫(huà)的效果將會(huì)從fromValue變化到fromValue+byValue
* toValue和byValue都不為空,動(dòng)畫(huà)的效果將會(huì)從toValue-byValue變化到toValue
* 只有fromValue的值不為空,動(dòng)畫(huà)的效果將會(huì)從fromValue的值變化到當(dāng)前的狀態(tài).
* 只有toValue的值不為空,動(dòng)畫(huà)的效果將會(huì)從當(dāng)前狀態(tài)的值變化到toValue的值.
* 只有byValue的值不為空,動(dòng)畫(huà)的效果將會(huì)從當(dāng)前的值變化到(當(dāng)前狀態(tài)的值+byValue)的值.
CABasicAnimation看起來(lái)不太復(fù)雜,但實(shí)際只用這個(gè)就足以可以做很多種動(dòng)畫(huà)了,下面簡(jiǎn)單用一下,先看效果:
![CABasicAnimation.gif](http://upload-images.jianshu.io/upload_images/2455429-518087d3167a598f.gif?imageMogr2/auto-orient/strip)
實(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)畫(huà)時(shí)間,單次動(dòng)畫(huà)時(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)畫(huà)時(shí)間不變,總動(dòng)畫(huà)時(shí)間增加一倍涛菠,它會(huì)讓你前半部分的動(dòng)畫(huà)以相反的方式動(dòng)畫(huà)過(guò)來(lái)
//比如說(shuō)你設(shè)置執(zhí)行一次動(dòng)畫(huà)俗冻,從a到b時(shí)間為1秒迄薄,設(shè)置自動(dòng)翻轉(zhuǎn)以后動(dòng)畫(huà)的執(zhí)行方式為涣易,先從a到b執(zhí)行一秒新症,然后從b到a再執(zhí)行一下動(dòng)畫(huà)結(jié)束
[animation setAutoreverses:YES];//kCAFillModeForwards//動(dòng)畫(huà)結(jié)束后回到準(zhǔn)備狀態(tài)
//kCAFillModeBackwards//動(dòng)畫(huà)結(jié)束后保持最后狀態(tài)
//kCAFillModeBoth//動(dòng)畫(huà)結(jié)束后回到準(zhǔn)備狀態(tài),并保持最后狀態(tài)
//kCAFillModeRemoved//執(zhí)行完成移除動(dòng)畫(huà)
[animation setFillMode:kCAFillModeBoth];//將動(dòng)畫(huà)添加到layer,添加到圖層開(kāi)始執(zhí)行動(dòng)畫(huà)徒爹,
//注意:key值的設(shè)置與否會(huì)影響動(dòng)畫(huà)的效果
//如果不設(shè)置key值每次執(zhí)行都會(huì)創(chuàng)建一個(gè)動(dòng)畫(huà)隆嗅,然后創(chuàng)建的動(dòng)畫(huà)會(huì)疊加在圖層上
//如果設(shè)置key值胖喳,系統(tǒng)執(zhí)行這個(gè)動(dòng)畫(huà)時(shí)會(huì)先檢查這個(gè)動(dòng)畫(huà)有沒(méi)有被創(chuàng)建,如果沒(méi)有的話就創(chuàng)建一個(gè)技健,如果有的話就重新從頭開(kāi)始執(zhí)行這個(gè)動(dòng)畫(huà)
//你可以通過(guò)key值獲取或者刪除一個(gè)動(dòng)畫(huà):
[self.opView.layer addAnimation:animation forKey:@"baseanimation"];
}
###CASpringAnimation彈性動(dòng)畫(huà)
**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)畫(huà)視圖的初始速度大小速率為正數(shù)時(shí),速度方向與運(yùn)動(dòng)方向一致,速率為負(fù)數(shù)時(shí),速度方向與運(yùn)動(dòng)方向相反.
@property CGFloat initialVelocity;
//結(jié)算時(shí)間,只讀.返回彈簧動(dòng)畫(huà)到停止時(shí)的估算時(shí)間确垫,根據(jù)當(dāng)前的動(dòng)畫(huà)參數(shù)估算通常彈簧動(dòng)畫(huà)的時(shí)間使用結(jié)算時(shí)間比較準(zhǔn)確
@property(readonly) CFTimeInterval settlingDuration;
下面我們寫(xiě)一個(gè)demo看看效果:
![](//upload-images.jianshu.io/upload_images/2455429-953b571f7664e583.gif)
實(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)畫(huà)
**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)畫(huà)的計(jì)算模式,默認(rèn)值: kCAAnimationLinear.有以下幾個(gè)值:
//kCAAnimationLinear//關(guān)鍵幀為座標(biāo)點(diǎn)的時(shí)候,關(guān)鍵幀之間直接直線相連進(jìn)行插值計(jì)算;
//kCAAnimationDiscrete//離散的,也就是沒(méi)有補(bǔ)間動(dòng)畫(huà)
//kCAAnimationPaced//平均翔冀,keyTimes跟timeFunctions失效
//kCAAnimationCubic對(duì)關(guān)鍵幀為座標(biāo)點(diǎn)的關(guān)鍵幀進(jìn)行圓滑曲線相連后插值計(jì)算,對(duì)于曲線的形狀還可以通過(guò)tensionValues,continuityValues,biasValues來(lái)進(jìn)行調(diào)整自定義,keyTimes跟timeFunctions失效
//kCAAnimationCubicPaced在kCAAnimationCubic的基礎(chǔ)上使得動(dòng)畫(huà)運(yùn)行變得均勻,就是系統(tǒng)時(shí)間內(nèi)運(yùn)動(dòng)的距離相同,,keyTimes跟timeFunctions失效
@property(copy) NSString *calculationMode;
//動(dòng)畫(huà)的張力,當(dāng)動(dòng)畫(huà)為立方計(jì)算模式的時(shí)候此屬性提供了控制插值,因?yàn)槊總€(gè)關(guān)鍵幀都可能有張力所以連續(xù)性會(huì)有所偏差它的范圍為[-1,1].同樣是此作用
@property(nullable, copy) NSArray *tensionValues;
//動(dòng)畫(huà)的連續(xù)性值
@property(nullable, copy) NSArray *continuityValues;
//動(dòng)畫(huà)的偏斜率
@property(nullable, copy) NSArray *biasValues;
//動(dòng)畫(huà)沿路徑旋轉(zhuǎn)方式,默認(rèn)為nil.它有兩個(gè)值:
//kCAAnimationRotateAuto//自動(dòng)旋轉(zhuǎn),
//kCAAnimationRotateAutoReverse//自動(dòng)翻轉(zhuǎn)
@property(nullable, copy) NSString *rotationMode;
**CAKeyframeAnimation**可以做很豐富的效果,下面展示了幾種純**CAKeyframeAnimation**做的效果:
![](//upload-images.jianshu.io/upload_images/2455429-4d17bc8a5d9b2bb1.gif)
實(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需要的類(lèi)型是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)畫(huà)組
**CAAnimationGroup**的屬性
//只有一個(gè)屬性,數(shù)組中接受CAAnimation元素
@property(nullable, copy) NSArray *animations;
可以看到CAAnimationGroup只有一個(gè)屬性一個(gè)CAAnimation數(shù)組.而且它繼承于CAAnimation,它具有CAAnimation的特性,所以它的用法和CAAnimation是一樣的,不同的是他可以包含n個(gè)動(dòng)畫(huà),也就是說(shuō)他可以接受很多個(gè)CAAnimation并且可以讓它們一起開(kāi)始,這就造成了動(dòng)畫(huà)效果的疊加,效果就是n個(gè)動(dòng)畫(huà)同時(shí)進(jìn)行.
來(lái)看一個(gè)簡(jiǎn)單的效果:
![](//upload-images.jianshu.io/upload_images/2455429-5cce294ff5a60e70.gif)
實(shí)現(xiàn)代碼:
-
(IBAction)animationBegin:(id)sender
{
CAAnimationGroup *group = [CAAnimationGroup animation];/**
- 移動(dòng)動(dòng)畫(huà)
/
CAKeyframeAnimation position = [self moveAnimation];
/ - 搖晃動(dòng)畫(huà)
/
CAKeyframeAnimation shake = [self shakeAnimation];
/ - 透明度動(dòng)畫(huà)
/
CABasicAnimation alpha = [self alphaAnimation];
/ - 設(shè)置動(dòng)畫(huà)組的時(shí)間,這個(gè)時(shí)間表示動(dòng)畫(huà)組的總時(shí)間,它的子動(dòng)畫(huà)的時(shí)間和這個(gè)時(shí)間沒(méi)有關(guān)系
*/
[group setDuration:3.0];
[group setAnimations:@[position,shake,alpha]];
[self.opView.layer addAnimation:group forKey:nil];
}
- 移動(dòng)動(dòng)畫(huà)
pragma mark -- CAKeyframeAnimation - 路徑平移動(dòng)畫(huà)
-(CAKeyframeAnimation )moveAnimation
{
CAKeyframeAnimation animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
/
* 設(shè)置路徑鹦赎,按圓運(yùn)動(dòng)
*/
CGMutablePathRef path = CGPathCreateMutable();//CG是C語(yǔ)言的框架古话,需要直接寫(xiě)語(yǔ)法
CGPathAddEllipseInRect(path, NULL, CGRectMake(0, 0, 320, 320));
[animation setPath:path];//把路徑給動(dòng)畫(huà)
CGPathRelease(path);//釋放路徑
/**
* 設(shè)置動(dòng)畫(huà)時(shí)間陪踩,這是動(dòng)畫(huà)總時(shí)間膊毁,不是每一幀的時(shí)間
*/
[animation setDuration:3];
/**
*setRemovedOnCompletion 設(shè)置動(dòng)畫(huà)完成后是否將圖層移除掉婚温,默認(rèn)是移除
*setFillMode 當(dāng)前設(shè)置的是向前填充栅螟,意味著動(dòng)畫(huà)完成后填充效果為最新的效果,此屬性有效的前提是 setRemovedOnCompletion=NO
*注意:
*1.動(dòng)畫(huà)只是改變?nèi)说囊曈X(jué)吃媒,它并不會(huì)改變視圖的初始位置等信息赘那,也就是說(shuō)無(wú)論動(dòng)畫(huà)怎么東募舟,都不會(huì)改變view的原始大小拱礁,只是看起來(lái)像是大小改變了而已
*2.因?yàn)闆](méi)有改變視圖的根本大小呢灶,所以視圖所接收事件的位置還是原來(lái)的大小鸯乃,可以不是顯示的大小
*/
[animation setRemovedOnCompletion:NO];
[animation setFillMode:kCAFillModeForwards];
return animation;
}
pragma mark -- CAKeyframeAnimation - 搖晃動(dòng)畫(huà)
-(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)畫(huà)時(shí)間宏蛉,這是動(dòng)畫(huà)總時(shí)間揍堰,不是每一幀的時(shí)間
*/
[animation setDuration:0.25];
return animation;
}
pragma mark -- CABasicAnimation - 淡如淡出動(dòng)畫(huà)
-(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)畫(huà)時(shí)間不變屏歹,總動(dòng)畫(huà)時(shí)間延遲一倍蝙眶,它會(huì)讓你前半部分的動(dòng)畫(huà)以相反的方式動(dòng)畫(huà)過(guò)來(lái)
* 比如說(shuō)你設(shè)置執(zhí)行一次動(dòng)畫(huà)幽纷,從a到b時(shí)間為1秒友浸,設(shè)置自動(dòng)翻轉(zhuǎn)以后動(dòng)畫(huà)的執(zhí)行方式為收恢,先從a到b執(zhí)行一秒,然后從b到a再執(zhí)行一下動(dòng)畫(huà)結(jié)束
/
[animation setAutoreverses:YES];
/*
* 設(shè)置起始值
/
[animation setFromValue:@1.0];
/*
* 設(shè)置目標(biāo)值
/
[animation setToValue:@0.1];
/*
* 將動(dòng)畫(huà)添加到layer 添加到圖層開(kāi)始執(zhí)行動(dòng)畫(huà)默赂,
* 注意:key值的設(shè)置與否會(huì)影響動(dòng)畫(huà)的效果
* 如果不設(shè)置key值每次執(zhí)行都會(huì)創(chuàng)建一個(gè)動(dòng)畫(huà),然后創(chuàng)建的動(dòng)畫(huà)會(huì)疊加在圖層上
* 如果設(shè)置key值疾捍,系統(tǒng)執(zhí)行這個(gè)動(dòng)畫(huà)時(shí)會(huì)先檢查這個(gè)動(dòng)畫(huà)有沒(méi)有被創(chuàng)建乱豆,如果沒(méi)有的話就創(chuàng)建一個(gè)瑟啃,如果有的話就重新從頭開(kāi)始執(zhí)行這個(gè)動(dòng)畫(huà)
* 你可以通過(guò)key值獲取或者刪除一個(gè)動(dòng)畫(huà)
*/
return animation;
}
### CATransition轉(zhuǎn)場(chǎng)動(dòng)畫(huà)
**CATransition**屬性
//轉(zhuǎn)場(chǎng)類(lèi)型,字符串類(lèi)型參數(shù).系統(tǒng)提供了四中動(dòng)畫(huà)形式:
//kCATransitionFade//逐漸消失
//kCATransitionMoveIn//移進(jìn)來(lái)
//kCATransitionPush//推進(jìn)來(lái)
//kCATransitionReveal//揭開(kāi)
//另外,除了系統(tǒng)給的這幾種動(dòng)畫(huà)效果,我們還可以使用系統(tǒng)私有的動(dòng)畫(huà)效果:
//@"cube",//立方體翻轉(zhuǎn)效果
//@"oglFlip",//翻轉(zhuǎn)效果
//@"suckEffect",//收縮效果,動(dòng)畫(huà)方向不可控
//@"rippleEffect",//水滴波紋效果,動(dòng)畫(huà)方向不可控
//@"pageCurl",//向上翻頁(yè)效果
//@"pageUnCurl",//向下翻頁(yè)效果
//@"cameralIrisHollowOpen",//攝像頭打開(kāi)效果,動(dòng)畫(huà)方向不可控
//@"cameraIrisHollowClose",//攝像頭關(guān)閉效果,動(dòng)畫(huà)方向不可控
@property(copy) NSString *type;
//轉(zhuǎn)場(chǎng)方向,系統(tǒng)一共提供四個(gè)方向:
//kCATransitionFromRight//從右開(kāi)始
//kCATransitionFromLeft//從左開(kāi)始
//kCATransitionFromTop//從上開(kāi)始
//kCATransitionFromBottom//從下開(kāi)始
@property(nullable, copy) NSString *subtype;
//開(kāi)始進(jìn)度,默認(rèn)0.0.如果設(shè)置0.3,那么動(dòng)畫(huà)將從動(dòng)畫(huà)的0.3的部分開(kāi)始
@property float startProgress;
//結(jié)束進(jìn)度,默認(rèn)1.0.如果設(shè)置0.6,那么動(dòng)畫(huà)將從動(dòng)畫(huà)的0.6部分以后就會(huì)結(jié)束
@property float endProgress;
//開(kāi)始進(jìn)度
@property(nullable, strong) id filter;
**CATransition**也是繼承**CAAnimation**,系統(tǒng)默認(rèn)提供了12種動(dòng)畫(huà)樣式,加上4個(gè)動(dòng)畫(huà)方向,除了方向不可控的四種效果外,大概一共提供了36種動(dòng)畫(huà).
另外系統(tǒng)還給UIView添加了很多分類(lèi)方法可以快速完成一些簡(jiǎn)單的動(dòng)畫(huà),如下:
**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)畫(huà) - (void)commitAnimations;
//設(shè)置代理 - (void)setAnimationDelegate:(nullable id)delegate; //設(shè)置動(dòng)畫(huà)開(kāi)始方法
- (void)setAnimationWillStartSelector:(nullable SEL)selector;
//設(shè)置動(dòng)畫(huà)結(jié)束方法 - (void)setAnimationDidStopSelector:(nullable SEL)selector;
//設(shè)置動(dòng)畫(huà)時(shí)間:default = 0.2 - (void)setAnimationDuration:(NSTimeInterval)duration;
//設(shè)置動(dòng)畫(huà)延遲開(kāi)始時(shí)間:default = 0.0 - (void)setAnimationDelay:(NSTimeInterval)delay;
//設(shè)置動(dòng)畫(huà)延遲開(kāi)始日期:default = now ([NSDate date]) - (void)setAnimationStartDate:(NSDate *)startDate;
//設(shè)置動(dòng)畫(huà)運(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)畫(huà): default = NO. used if repeat - (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses;
//設(shè)置動(dòng)畫(huà)是否從當(dāng)前狀態(tài)開(kāi)始:default = NO - (void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState;
//設(shè)置動(dòng)畫(huà)類(lèi)型 - (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache;
//設(shè)置動(dòng)畫(huà)是否有效 - (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
以上方法比較多,找值得說(shuō)的簡(jiǎn)單說(shuō)一下吧:
//單視圖轉(zhuǎn)場(chǎng)動(dòng)畫(huà)
- (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)畫(huà) - (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)畫(huà),不同的是第一個(gè)是單視圖轉(zhuǎn)場(chǎng),第二個(gè)是雙視圖轉(zhuǎn)場(chǎng).不過(guò)需要注意的是:單視圖轉(zhuǎn)場(chǎng)動(dòng)畫(huà)只能用作屬性動(dòng)畫(huà)做不到的轉(zhuǎn)場(chǎng)效果,比如屬性動(dòng)畫(huà)不能給UIImageview的image賦值操作做動(dòng)畫(huà)效果等.
我們可以看到以上兩個(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)畫(huà)效果**
UIViewAnimationOptionTransitionNone//沒(méi)有效果
UIViewAnimationOptionTransitionFlipFromLeft//從左水平翻轉(zhuǎn)
UIViewAnimationOptionTransitionFlipFromRight//從右水平翻轉(zhuǎn)
UIViewAnimationOptionTransitionCurlUp//翻書(shū)上掀
UIViewAnimationOptionTransitionCurlDown//翻書(shū)下蓋UIViewAnimationOptionTransitionCrossDissolve//融合
UIViewAnimationOptionTransitionFlipFromTop//從上垂直翻轉(zhuǎn)
UIViewAnimationOptionTransitionFlipFromBottom//從下垂直翻轉(zhuǎn)
**第二部分:動(dòng)畫(huà)運(yùn)動(dòng)曲線**
//開(kāi)始慢犹撒,加速到中間识颊,然后減慢到結(jié)束
UIViewAnimationOptionCurveEaseInOut
//開(kāi)始慢谊囚,加速到結(jié)束
UIViewAnimationOptionCurveEaseIn
//開(kāi)始快镰踏,減速到結(jié)束
UIViewAnimationOptionCurveEaseOut
//線性運(yùn)動(dòng)
UIViewAnimationOptionCurveLinear
**第三部分:其他**
//默認(rèn),跟父類(lèi)作為一個(gè)整體
UIViewAnimationOptionLayoutSubviews
//設(shè)置了這個(gè)绊率,主線程可以接收點(diǎn)擊事件
UIViewAnimationOptionAllowUserInteraction
//從當(dāng)前狀態(tài)開(kāi)始動(dòng)畫(huà)滤否,父層動(dòng)畫(huà)運(yùn)動(dòng)期間藐俺,開(kāi)始子層動(dòng)畫(huà).
UIViewAnimationOptionBeginFromCurrentState
//重復(fù)執(zhí)行動(dòng)畫(huà)欲芹,從開(kāi)始到結(jié)束菱父, 結(jié)束后直接跳到開(kāi)始態(tài)
**UIViewAnimationOptionRepeat**
//反向執(zhí)行動(dòng)畫(huà)浙宜,結(jié)束后會(huì)再?gòu)慕Y(jié)束態(tài)->開(kāi)始態(tài)
UIViewAnimationOptionAutoreverse
//忽略繼承自父層持續(xù)時(shí)間粟瞬,使用自己持續(xù)時(shí)間(如果存在)
UIViewAnimationOptionOverrideInheritedDuration
//忽略繼承自父層的線性效果乓梨,使用自己的線性效果(如果存在)
UIViewAnimationOptionOverrideInheritedCurve
//允許同一個(gè)view的多個(gè)動(dòng)畫(huà)同時(shí)進(jìn)行
UIViewAnimationOptionAllowAnimatedContent
//視圖切換時(shí)直接隱藏舊視圖扶镀、顯示新視圖臭觉,而不是將舊視圖從父視圖移除(僅僅適用于轉(zhuǎn)場(chǎng)動(dòng)畫(huà)) UIViewAnimationOptionShowHideTransitionViews
//不繼承父動(dòng)畫(huà)設(shè)置或動(dòng)畫(huà)類(lèi)型.
UIViewAnimationOptionOverrideInheritedOptions
這下可以看到,這些枚舉功能都不一樣但是可以隨意組合,但是組合的時(shí)候需要注意,同一類(lèi)型的枚舉不能一起使用比如UIViewAnimationOptionCurveEaseIn和UIViewAnimationOptionCurveEaseOut
然后我們看一下轉(zhuǎn)場(chǎng)動(dòng)畫(huà)的一些效果:
**單視圖轉(zhuǎn)場(chǎng)**
![單視圖轉(zhuǎn)場(chǎng).gif](http://upload-images.jianshu.io/upload_images/2455429-9b985706162c02b9.gif?imageMogr2/auto-orient/strip)
**雙視圖轉(zhuǎn)場(chǎng)**
![雙視圖轉(zhuǎn)場(chǎng).gif](http://upload-images.jianshu.io/upload_images/2455429-64442b994e0d1b76.gif?imageMogr2/auto-orient/strip)
**CATransition轉(zhuǎn)場(chǎng)**
![CATransition轉(zhuǎn)場(chǎng).gif](http://upload-images.jianshu.io/upload_images/2455429-ef67070f27e696f1.gif?imageMogr2/auto-orient/strip)
實(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)畫(huà)在執(zhí)行過(guò)程中不可以被停止,
- 轉(zhuǎn)場(chǎng)動(dòng)畫(huà)在執(zhí)行過(guò)程中不可以用戶(hù)交互
- 轉(zhuǎn)場(chǎng)動(dòng)畫(huà)在執(zhí)行過(guò)程中不可以控制動(dòng)畫(huà)執(zhí)行進(jìn)度
/
/* - 基于UIView的單視圖轉(zhuǎn)場(chǎng)動(dòng)畫(huà)
*/
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),//翻書(shū)上掀
@(UIViewAnimationOptionTransitionCurlDown),//翻書(shū)下蓋
@(UIViewAnimationOptionTransitionCrossDissolve),//融合
@(UIViewAnimationOptionTransitionFlipFromTop),//從上垂直翻轉(zhuǎn)
@(UIViewAnimationOptionTransitionFlipFromBottom),//從下垂直翻轉(zhuǎn)
];
/**
* 第二部分
*/
NSArray *array1 = @[
@(UIViewAnimationOptionCurveEaseInOut),////開(kāi)始慢什乙,加速到中間,然后減慢到結(jié)束
@(UIViewAnimationOptionCurveEaseIn),//開(kāi)始慢忆某,加速到結(jié)束
@(UIViewAnimationOptionCurveEaseOut),//開(kāi)始快弃舒,減速到結(jié)束
@(UIViewAnimationOptionCurveLinear),//線性運(yùn)動(dòng)
];
/**
* 第三部分
*/
NSArray *array2 = @[
@(UIViewAnimationOptionLayoutSubviews),//默認(rèn)聋呢,跟父類(lèi)作為一個(gè)整體
@(UIViewAnimationOptionAllowUserInteraction),//設(shè)置了這個(gè)坝冕,主線程可以接收點(diǎn)擊事件
@(UIViewAnimationOptionBeginFromCurrentState),//從當(dāng)前狀態(tài)開(kāi)始動(dòng)畫(huà),父層動(dòng)畫(huà)運(yùn)動(dòng)期間,開(kāi)始子層動(dòng)畫(huà)央串。
@(UIViewAnimationOptionRepeat),//重復(fù)執(zhí)行動(dòng)畫(huà)磨澡,從開(kāi)始到結(jié)束, 結(jié)束后直接跳到開(kāi)始態(tài)
@(UIViewAnimationOptionAutoreverse),//反向執(zhí)行動(dòng)畫(huà)质和,結(jié)束后會(huì)再?gòu)慕Y(jié)束態(tài)->開(kāi)始態(tài)
@(UIViewAnimationOptionOverrideInheritedDuration),//忽略繼承自父層持續(xù)時(shí)間稳摄,使用自己持續(xù)時(shí)間(如果存在)
@(UIViewAnimationOptionOverrideInheritedCurve),//忽略繼承自父層的線性效果,使用自己的線性效果(如果存在)
@(UIViewAnimationOptionAllowAnimatedContent),//允許同一個(gè)view的多個(gè)動(dòng)畫(huà)同時(shí)進(jìn)行
@(UIViewAnimationOptionShowHideTransitionViews),//視圖切換時(shí)直接隱藏舊視圖饲宿、顯示新視圖,而不是將舊視圖從父視圖移除(僅僅適用于轉(zhuǎn)場(chǎng)動(dòng)畫(huà))
@(UIViewAnimationOptionOverrideInheritedOptions),//不繼承父動(dòng)畫(huà)設(shè)置或動(dòng)畫(huà)類(lèi)型瘫想。
];
// 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)畫(huà)需要在動(dòng)畫(huà)塊中設(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)畫(huà):%s:%@:%@:%@",__func__,@(change1_0Index),@(change1_1Index),@(change1_2Index));
}
else
{
/**
* 雙視圖的轉(zhuǎn)場(chǎng)動(dòng)畫(huà)
* 注意:雙視圖的轉(zhuǎn)場(chǎng)動(dòng)畫(huà)實(shí)際上是操作視圖移除和添加到父視圖的一個(gè)過(guò)程仗阅,from視圖必須要有父視圖,to視圖必須不能有父視圖国夜,否則會(huì)出問(wèn)題
* 比如動(dòng)畫(huà)不準(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)畫(huà)
/
static NSUInteger change3_0Index = 0;
static NSUInteger change3_1Index = 0;
-(void)chang3
{
/*
*創(chuàng)建轉(zhuǎn)場(chǎng)動(dòng)畫(huà):注意:CATransaction和CATransition 不一樣
*/
CATransition *transition = [CATransition animation];transition.duration = 0.25;
NSArray *type_array = @[
//系統(tǒng)提供的動(dòng)畫(huà)
kCATransitionFade,
kCATransitionMoveIn,
kCATransitionPush,
kCATransitionReveal,//以下是私有api,只能字符串訪問(wèn) @"cube",//立方體翻轉(zhuǎn)效果 @"oglFlip",//翻轉(zhuǎn)效果 @"suckEffect",//收縮效果,動(dòng)畫(huà)方向不可控 @"rippleEffect",//水滴波紋效果,動(dòng)畫(huà)方向不可控 @"pageCurl",//向上翻頁(yè)效果 @"pageUnCurl",//向下翻頁(yè)效果 @"cameralIrisHollowOpen",//攝像頭打開(kāi)效果,動(dòng)畫(huà)方向不可控 @"cameraIrisHollowClose",//攝像頭關(guān)閉效果,動(dòng)畫(huà)方向不可控 ];
//轉(zhuǎn)場(chǎng)類(lèi)型
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)畫(huà)的開(kāi)始和結(jié)束百分比
*/
transition.startProgress = 0.0;
transition.endProgress = 1.0;
- 設(shè)置轉(zhuǎn)場(chǎng)動(dòng)畫(huà)的開(kāi)始和結(jié)束百分比
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)畫(huà):%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;
}
}