iOS 動(dòng)畫(huà)之CoreAnimation(CALayer)

CoreAnimation基本介紹

CoreAnimation動(dòng)畫(huà)位于iOS框架的Media

CoreAnimation動(dòng)畫(huà)實(shí)現(xiàn)需要添加QuartzCore.Framework

CoreAnimation基本上是Layer Animation

CoreAnimation分類(lèi)

隱式動(dòng)畫(huà):無(wú)需指定任何動(dòng)畫(huà)的類(lèi)型,僅僅改變一個(gè)屬性,然后CoreAnimation來(lái)決定

如何計(jì)時(shí)去做動(dòng)畫(huà)。

顯示動(dòng)畫(huà):對(duì)一些屬性做指定的自定義動(dòng)畫(huà),或創(chuàng)建非線性動(dòng)畫(huà),比如沿著任意一條曲線移動(dòng)。

CoreAnimation作用

與UIView動(dòng)畫(huà)相比,CoreAnimation能夠?qū)崿F(xiàn)更多復(fù)雜、好看、高效的動(dòng)畫(huà)效果。

陰影,圓角,帶顏色的邊框。

3D變化。

透明遮罩

多級(jí)非線性動(dòng)畫(huà)

CoreAnimation的三種動(dòng)畫(huà)

CABasicAnimation基本單一類(lèi)型的動(dòng)畫(huà),通過(guò)設(shè)定起始點(diǎn),終點(diǎn),時(shí)間,動(dòng)畫(huà)會(huì)沿著你這設(shè)定點(diǎn)進(jìn)行移動(dòng)。可以看做特殊的CAKeyFrameAnimation 。

CAKeyframeAnimation幀動(dòng)畫(huà)主要操作屬性有keyPathvalues值組合Keyframe顧名思義就是關(guān)鍵點(diǎn)的frame,你可以通過(guò)設(shè)定CALayer的始點(diǎn)、中間關(guān)鍵點(diǎn)、終點(diǎn)的frame,時(shí)間,動(dòng)畫(huà)會(huì)沿你設(shè)定的軌跡進(jìn)行移動(dòng)。

CAAnimationGroup組合動(dòng)畫(huà) 操作屬性animationsCAAnimation類(lèi)型的動(dòng)畫(huà)加入數(shù)組,以FIFO隊(duì)列的方式執(zhí)行。

CATransition這個(gè)就是蘋(píng)果幫開(kāi)發(fā)者封裝好的一些動(dòng)畫(huà)

CABasicAnimation

三個(gè)重要的屬性

@property(nullable,strong)idfromValue;動(dòng)畫(huà)的效果變化的初始值@property(nullable,strong)idtoValue;動(dòng)畫(huà)效果變化的結(jié)束值(絕對(duì)值)@property(nullable,strong)idbyValue;動(dòng)畫(huà)效果變化的結(jié)束值(相對(duì)值)

這三個(gè)屬性必須要有一個(gè)有值,它們的值就是原來(lái)視圖的放大,旋轉(zhuǎn)等倍數(shù)或者角度。

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

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

toValuebyValue都不為空,動(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)的值。

想要實(shí)現(xiàn)不同的效果,最關(guān)鍵的地方在于CABasicAnimation對(duì)象的初始化方式中keyPath的設(shè)定。在iOS中有以下幾種不同的keyPath,代表著不同的效果:

transform.rotation.x//以x軸為中心旋轉(zhuǎn)transform.rotation.y//以y軸為中心旋轉(zhuǎn)transform.rotation.z//以z軸為中心旋轉(zhuǎn)transform.scale.x//縮放x軸方向transform.scale.y//縮放y軸方向transform.scale.z//縮放z軸方向,這個(gè)一般不會(huì)用到。transform.scale//x,y方向整體縮放,z方向沒(méi)看到效果。

下面我們來(lái)簡(jiǎn)單的做一個(gè)動(dòng)畫(huà)

- (void)springAnimation{? ? CABasicAnimation *base= [CABasicAnimation animationWithKeyPath:@"transform.scale.y"];/*在動(dòng)畫(huà)結(jié)束之后是否讓動(dòng)畫(huà)回到原處,這個(gè)屬性的默認(rèn)值是YES(回到原處),此時(shí)*fillMode*是沒(méi)有作用的

如果設(shè)置為NO那么就需要設(shè)置一個(gè)*fillMode*屬性,就是動(dòng)畫(huà)結(jié)束之后的狀態(tài),如果不設(shè)置,動(dòng)畫(huà)也會(huì)回到原處。*/base.removedOnCompletion = NO;//動(dòng)畫(huà)結(jié)束之后狀態(tài)的設(shè)置base.fillMode = kCAFillModeForwards;base.fromValue = @(2);//動(dòng)畫(huà)時(shí)長(zhǎng)base.duration =10;//動(dòng)畫(huà)的重復(fù)次數(shù)base.repeatCount =100;//給base動(dòng)畫(huà)設(shè)置延時(shí)啟動(dòng)base.beginTime =2+ CACurrentMediaTime();//動(dòng)畫(huà)是否按原路徑返回base.autoreverses = YES;//將動(dòng)畫(huà)添加到layer層*forKey*是給動(dòng)畫(huà)添加一個(gè)標(biāo)記,方便刪除。[self.redView.layer addAnimation:baseforKey:@"basic"];}

刪除動(dòng)畫(huà)的方法

-(void)removeAnimationForKey:(NSString*)key;key:你需要?jiǎng)h除的動(dòng)畫(huà)的名稱(chēng)。這個(gè)方法就是你把動(dòng)畫(huà)添加到那個(gè)視圖的layer層上,就由那個(gè)視圖的layer來(lái)調(diào)用。-(void)removeAllAnimations;這個(gè)法是刪除這個(gè)視圖layer層上的所有動(dòng)畫(huà)。

在這里簡(jiǎn)單介紹一下fillMode

注意fillMode這個(gè)屬性,必須要配合下面這個(gè)屬性來(lái)使用。這個(gè)屬性的默認(rèn)值是YES(回到原處),此時(shí)fillMode是沒(méi)有作用的如果設(shè)置為NO那么就需要設(shè)置一個(gè)fillMode屬性,就是動(dòng)畫(huà)結(jié)束之后的狀態(tài),如果不設(shè)置,動(dòng)畫(huà)也會(huì)回到原處。

base.removedOnCompletion=NO;

kCAFillModeRemoved這個(gè)是默認(rèn)值,也就是說(shuō)當(dāng)動(dòng)畫(huà)開(kāi)始前和動(dòng)畫(huà)結(jié)束后,動(dòng)畫(huà)對(duì)layer都沒(méi)有影響,動(dòng)畫(huà)結(jié)束后,layer會(huì)恢復(fù)到之前的狀態(tài) kCAFillModeForwards當(dāng)動(dòng)畫(huà)結(jié)束后,layer會(huì)一直保持著動(dòng)畫(huà)最后的狀態(tài) kCAFillModeBackwards這個(gè)和kCAFillModeForwards是相對(duì)的,就是在動(dòng)畫(huà)開(kāi)始前,你只要將動(dòng)畫(huà)加入了一個(gè)layer,layer便立即進(jìn)入動(dòng)畫(huà)的初始狀態(tài)并等待動(dòng)畫(huà)開(kāi)始.你可以這樣設(shè)定測(cè)試代碼,將一個(gè)動(dòng)畫(huà)加入一個(gè)layer的時(shí)候延遲5秒執(zhí)行.然后就會(huì)發(fā)現(xiàn)在動(dòng)畫(huà)沒(méi)有開(kāi)始的時(shí)候,只要?jiǎng)赢?huà)被加入了layer,layer便處于動(dòng)畫(huà)初始狀態(tài) kCAFillModeBoth理解了上面兩個(gè),這個(gè)就很好理解了,這個(gè)其實(shí)就是上面兩個(gè)的合成.動(dòng)畫(huà)加入后開(kāi)始之前,layer便處于動(dòng)畫(huà)初始狀態(tài),動(dòng)畫(huà)結(jié)束后layer保持動(dòng)畫(huà)最后的狀態(tài).

CAKeyframeAnimation

這個(gè)動(dòng)畫(huà)可以讓你在動(dòng)畫(huà)的一些關(guān)鍵的位置來(lái)改變動(dòng)畫(huà)的frame以此來(lái)達(dá)到我們想要的效果。

position是描述動(dòng)畫(huà)視圖的位置信息的,簡(jiǎn)單理解就是和視圖的中心點(diǎn)一樣,所以我們通過(guò)改變position屬性,就可以改變動(dòng)畫(huà)的位置。

position相對(duì)應(yīng)得是錨點(diǎn)也就是anchorPointanchorPoint、position、frame這三者之間有著如下的關(guān)系。

position.x = frame.origin.x + anchorPoint.x * bounds.size.width; position.y = frame.origin.y + anchorPoint.y * bounds.size.height;

示例代碼:下面是讓一個(gè)視圖左右震動(dòng)的動(dòng)畫(huà)

CAKeyframeAnimation*keyFram = [CAKeyframeAnimationanimationWithKeyPath:@"position"];//layer最初的position值floatposition_x =self.redView.layer.position.x;floatposition_y =self.redView.layer.position.y;//layer向左晃動(dòng)的偏移量NSValue*leftValue = [NSValuevalueWithCGPoint:CGPointMake(position_x -30, position_y)];//layer的原始位置NSValue*originValue = [NSValuevalueWithCGPoint:CGPointMake(position_x, position_y)];//layer向右晃動(dòng)的偏移量NSValue*right = [NSValuevalueWithCGPoint:CGPointMake(position_x +30, position_y)];//添加每一幀的Value值[keyFram setValues:@[originValue,leftValue,originValue,right,originValue]];? ? keyFram.repeatCount=10;? ? keyFram.repeatDuration=1;//為layer層添加動(dòng)畫(huà)[self.redView.layeraddAnimation:keyFram forKey:@"aaa"];

CAAnimationGroup

CAAnimationGroup是一個(gè)組合動(dòng)畫(huà),所謂的組合動(dòng)畫(huà)就是將多個(gè)動(dòng)畫(huà)組合到一起讓它產(chǎn)生很炫酷的效果。

注意:所有的組合動(dòng)畫(huà),它的延遲啟動(dòng),重復(fù)次數(shù)等屬性,同一在組里面設(shè)置,不要在單一的動(dòng)畫(huà)里面設(shè)置,以免出現(xiàn)問(wèn)題。

第一步:初始化組合動(dòng)畫(huà)

CAAnimationGroup*group = [CAAnimationGroupanimation];

第二步創(chuàng)建至少兩個(gè)動(dòng)畫(huà)

CABasicAnimation*base = [CABasicAnimationanimationWithKeyPath:@"transform.rotation.z"];/*在動(dòng)畫(huà)結(jié)束之后是否讓動(dòng)畫(huà)回到原處,這個(gè)屬性的默認(rèn)值是YES(回到原處),此時(shí)*fillMode*是沒(méi)有作用的

如果設(shè)置為NO那么就需要設(shè)置一個(gè)*fillMode*屬性,就是動(dòng)畫(huà)結(jié)束之后的狀態(tài),如果不設(shè)置,動(dòng)畫(huà)也會(huì)回到原處。*/base.removedOnCompletion=NO;//動(dòng)畫(huà)結(jié)束之后狀態(tài)的設(shè)置base.fillMode= kCAFillModeForwards;? base.fromValue= @(M_PI);//動(dòng)畫(huà)是否按原路徑返回base.autoreverses=YES;/************************************************************************************************/CAKeyframeAnimation*keyFram = [CAKeyframeAnimationanimationWithKeyPath:@"position"];//layer最初的position值floatposition_x =self.redView.layer.position.x;floatposition_y =self.redView.layer.position.y;//layer向左晃動(dòng)的偏移量NSValue*leftValue = [NSValuevalueWithCGPoint:CGPointMake(position_x -50, position_y)];//layer的原始位置NSValue*originValue = [NSValuevalueWithCGPoint:CGPointMake(position_x, position_y)];//layer向右晃動(dòng)的偏移量NSValue*right = [NSValuevalueWithCGPoint:CGPointMake(position_x +50, position_y)];//添加每一幀的Value值[keyFram setValues:@[originValue,leftValue,originValue,right,originValue]];

第三步將得到的動(dòng)畫(huà)放入group中

group.animations = @[base,keyFram];//將group加到layer上group.repeatCount =100;group.repeatDuration =10;? [self.redView.layer addAnimation:groupforKey:@"group"];

最后編輯于
?著作權(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),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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