iOS動(dòng)畫進(jìn)階 - CAKeyframeAnimation實(shí)現(xiàn)過山車動(dòng)畫

··~~~~因?yàn)楣ぷ髟蛐枰獙?duì)動(dòng)畫有所了解,由于之前用的很少,這方面的知識(shí)很匱乏,所以借此機(jī)會(huì)深入的了解了下關(guān)于動(dòng)畫方面的知識(shí),由于沒有找到好的動(dòng)畫效果,就高仿了一個(gè)用CAKeyframeAnimation實(shí)現(xiàn)的過山車動(dòng)畫~~~~~~~嗚嗚嗚

1505202465905.jpg

動(dòng)態(tài)果圖:http://ww4.sinaimg.cn/large/006tNbRwgw1f53ahi8vslg30if0a8e81

項(xiàng)目中主要用到的類

  • CAShapeLayer
  • CAGradientLayer
  • CAKeyframeAnimation
漸變的天空背景色使用CAGradientLayer類來生成兩種或更多的漸變平滑的顏色,草坪和軌道使用CAShapeLayer配合UIBezierPath(貝塞爾曲線)完成,云朵、大地和大樹可以通過CALayer設(shè)置contents屬性來實(shí)現(xiàn)(注:如果給CALayer設(shè)置color或imaeg屬性時(shí),需要將color轉(zhuǎn)換為CGColor,image轉(zhuǎn)換為CGImage,不然圖片或顏色不顯示---),云朵和過山車的動(dòng)畫可以使用CAKeyframeAnimation來實(shí)現(xiàn),是不是看起來好簡單~~~~

---------------------------------下面是每個(gè)類的功能介紹---------------------------------

CAShapeLayer

  • 1、CAShapeLayer是一種特殊的層,可以在上面渲染圖形。
  • 2、CAShapeLayer繼承自CALayer,可使用CALayer的所有屬性。
  • 3、CAShapeLayer需要和貝塞爾曲線配合使用才有意義,貝塞爾曲線為其提供渲染的圖形。
  • 4、使用CAShapeLayer與貝塞爾曲線可以實(shí)現(xiàn)不再view的drawRect方法中畫出一些想要的圖形。
CAShapeLayer是一個(gè)通過矢量圖形而不是bitmap來繪制的圖層子類, CAShapeLayer相當(dāng)于使用畫筆直接在圖層上繪制想要的圖片,通過GPU來渲染圖形,如果使用drawRect來繪制圖形是調(diào)用CoreGraphics框架中得方法,占用CPU,消耗性能大(那簡直要卡爆了)。使用CAShapeLayer你可以指定諸如顏色和線寬等屬性,用CGPath來定義想要繪制的圖形,最后CAShapeLayer就自動(dòng)渲染出來了。當(dāng)然,你也可以用Core Graphics直接向原始的CALyer的內(nèi)容中繪制一個(gè)路徑,相比直下,使用CAShapeLayer有以下一些優(yōu)點(diǎn):
  • 渲染快速。CAShapeLayer使用了硬件加速,繪制同一圖形會(huì)比用Core Graphics快很多。
  • 高效使用內(nèi)存。一個(gè)CAShapeLayer不需要像普通CALayer一樣創(chuàng)建一個(gè)寄宿圖形,所以無論有多大,都不會(huì)占用太多的內(nèi)存。
  • 不會(huì)被圖層邊界剪裁掉。一個(gè)CAShapeLayer可以在邊界之外繪制。你的圖層路徑不會(huì)像在使用Core Graphics的普通CALayer一樣被剪裁掉
  • 不會(huì)出現(xiàn)像素化。當(dāng)你給CAShapeLayer做3D變換時(shí),它不像一個(gè)有寄宿圖的普通圖層一樣變得像素化。

使用CAShapeLayer來繪制草地的代碼:

 //第一塊草坪
    self.shapeLayer = [CAShapeLayer layer];
    //通過貝塞爾曲線繪制路徑
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(0, kScreenWidth - 20)];//設(shè)置曲線的起點(diǎn)
    [path addLineToPoint:CGPointMake(0, kScreenWidth - 100)];//連線到某點(diǎn)
    [path addQuadCurveToPoint:CGPointMake(kScreenHeight / 3.0, kScreenWidth - 20) controlPoint:CGPointMake(kScreenHeight / 6.0, kScreenWidth - 100)];//設(shè)置終點(diǎn)和控制點(diǎn),控制點(diǎn)越小繪制的圖形越大越高
    
    self.shapeLayer.path = path.CGPath;
    self.shapeLayer.fillColor = [UIColor colorWithRed:82.0/255.0 green:177.0/255.0 blue:44.0/255.0 alpha:1.0].CGColor;//設(shè)置填充色
    [self.backV.layer addSublayer:self.shapeLayer];
    
    //第二塊草坪
    
    CAShapeLayer *shapeLayer2 = [CAShapeLayer layer];
    UIBezierPath *path2 = [UIBezierPath bezierPath];
    [path2 moveToPoint:CGPointMake(0, kScreenWidth - 20)];
    [path2 addQuadCurveToPoint:CGPointMake(kScreenHeight, kScreenWidth - 60) controlPoint:CGPointMake(kScreenHeight / 2.0, kScreenWidth - 150)];
    [path2 addLineToPoint:CGPointMake(kScreenHeight, kScreenWidth - 20)];
    shapeLayer2.path = path2.CGPath;

    shapeLayer2.fillColor = [UIColor colorWithRed:92.0/255.0 green:195.0/255.0 blue:52.0/255.0 alpha:1.0].CGColor;
    [self.backV.layer addSublayer:shapeLayer2];

效果圖:

006tNbRwgw1f53ba1snf4j30ij0agtc7.jpg

CAGradientLayer

CAGradientLayer 簡介

  • CAGradientLayer是CALayer圖層類的子類,用于處理漸變色的層結(jié)構(gòu)。
  • CAGradientLayer的漸變色可以做隱式動(dòng)畫。
  • CAGradientLayer和CAShapeLayer配合使用可實(shí)現(xiàn)復(fù)雜效果。
  • CAGradientLayer可以用作PNG的遮罩效果。
  • CAGradientLayer 坐標(biāo)系統(tǒng)
1339729-c2ec801415d3aca9.png
  • CAGradientLayer的坐標(biāo)系統(tǒng)是從坐標(biāo)(0,0)到(1,1)繪制的矩形。
  • CAGradientLayer的frame值的size不為正方形的話,坐標(biāo)系統(tǒng)會(huì)被拉伸。
  • CAGradientLayer的startPoint與endPoint會(huì)直接影響顏色的繪制方向。
  • CAGradientLayer的顏色分割點(diǎn)是以0~1的比例來計(jì)算的,顏色分割點(diǎn)為漸變色開始或終止的地方。

CAGradientLayer 屬性介紹

  • colors:漸變顏色數(shù)組
  • locations:漸變顏色的區(qū)間分布(分割點(diǎn)),locations的數(shù)組長度和colors一致。這個(gè)屬性可不設(shè),默認(rèn)是nil,系統(tǒng)會(huì)平均分布顏色如果有特定需要可設(shè)置,數(shù)組設(shè)置為0 ~ 1之間單調(diào)遞增。
  • startPoint:映射locations中起始位置,用單位向量表示。比如(0, 0)表示從左上角開始變化。默認(rèn)值是:(0.5, 0.0)。
  • endPoint:映射locations中結(jié)束位置,用單位向量表示。比如(1, 1)表示到右下角變化結(jié)束。默認(rèn)值是:(0.5, 1.0)。
  • type:默認(rèn)值是kCAGradientLayerAxial,表示按像素均勻變化。

使用CAGradientLayer來實(shí)現(xiàn)了項(xiàng)目中天空背景的繪制,效果圖:

006tNbRwgw1f53ax28scyj30ij09w74d.jpg

天空背景代碼:

 //初始化 背景
    
     self.CAGLayer = [CAGradientLayer layer];
     self.CAGLayer.frame = self.backV.bounds;
    //設(shè)置漸變的顏色
     self.CAGLayer.colors = @[(id)[UIColor colorWithRed:178.0/255.0 green:226.0/255.0 blue:248.0/255.0 alpha:1.0].CGColor,
                      (id)[UIColor colorWithRed:232.0/255.0 green:244.0/255.0 blue:193.0/255.0 alpha:1.0].CGColor];
    //設(shè)置漸變的方向 自左上到右下
     self.CAGLayer.startPoint = CGPointMake(0, 0);
     self.CAGLayer.endPoint = CGPointMake(1, 1);
    [self.backV.layer addSublayer: self.CAGLayer];

CAKeyframeAnimation

CAKeyframeAnimation簡介

  • CAKeyframeAnimation又稱關(guān)鍵幀動(dòng)畫
  • CAKeyframeAnimation是抽象類CAPRopertyAnimation的子類,可以直接使用
  • 通過values與path兩個(gè)屬性指定動(dòng)畫屬性

注意事項(xiàng)

  • 若指定了path屬性,則values屬性將被忽略
  • CABasicAnimation相當(dāng)于只有兩個(gè)關(guān)鍵幀的CAKeyframeAnimation

CAKeyframeAnimation 屬性介紹

  • values(NSArray *)存放關(guān)鍵幀的多個(gè)值,類似于CABasicAnimation的fromValue與toValue值
  • path(CGPathRef)動(dòng)畫的執(zhí)行路徑,可以通過繪圖的方式繪制路徑
  • keyTimes(NSArray *)每個(gè)關(guān)鍵幀的執(zhí)行時(shí)間,類型為NSNumber類型,若不指定,則所有的關(guān)鍵幀平分動(dòng)畫的duration時(shí)長
  • timingFunctions(NSArray *)速度控制函數(shù)數(shù)組
  • calculationMode(NSString *)指定關(guān)鍵幀的動(dòng)畫屬性,若指定該值,則keyTimes與timingFunctions屬性值將被忽略,默認(rèn)為:kCAAnimationLinear
  • rotationMode(NSString *)指定旋轉(zhuǎn)模式,默認(rèn)為nil
CAKeyframeAnimation類為對(duì)象提供了關(guān)鍵幀動(dòng)畫的功能。你創(chuàng)建一個(gè)CAKeyframeAnimation對(duì)象使用animationWithKeyPath:指定屬性的關(guān)鍵路徑,你可以指定要使用關(guān)鍵幀的值來控制時(shí)間和動(dòng)畫的行為。我們可以通過CAKeyframeAnimation來實(shí)現(xiàn)過山車在軌道上的的動(dòng)畫和云朵的動(dòng)畫:
1505206576473.jpg
代碼如下:
 CALayer *carLayer = [CALayer layer];
    carLayer.frame = CGRectMake(0, 0, 17, 11);
    UIImage *image = [UIImage imageNamed:@"othercar"];
    CGImageRef imageRef = image.CGImage;
    carLayer.contents = (__bridge id _Nullable)(imageRef);

    UIBezierPath *bluePath  = [UIBezierPath bezierPath];
    bluePath.lineCapStyle = kCGLineCapRound;
    bluePath.lineJoinStyle = kCGLineCapRound;
    [bluePath  moveToPoint:CGPointMake(kScreenWidth2 +10, kScreenHeight2 - 7)];
    [bluePath addLineToPoint:CGPointMake(kScreenWidth2 + 10, kScreenHeight2 - 77)];
    [bluePath addQuadCurveToPoint:CGPointMake(kScreenWidth2 / 1.8, kScreenHeight2 - 77) controlPoint:CGPointMake(kScreenWidth2 - 120, 193)];
    [bluePath addArcWithCenter:CGPointMake(kScreenWidth2 / 1.9, kScreenHeight2 - 140) radius:63 startAngle:0.5*M_PI endAngle:2.5*M_PI clockwise:true];
    
    [bluePath addCurveToPoint:CGPointMake(0, kScreenHeight2 - 107) controlPoint1:CGPointMake(kScreenWidth2 /1.8 - 60, kScreenHeight2 - 67) controlPoint2:CGPointMake(150, kScreenHeight2 /2.3 -7)];
    [bluePath addLineToPoint:CGPointMake(-100, kScreenHeight2 +7)];
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];//簡單的創(chuàng)建一個(gè)帶路徑的動(dòng)畫效果,比較粗糙
    animation.path = bluePath.CGPath;
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];//CAMediaTiming協(xié)議定義了在一段動(dòng)畫內(nèi)用來控制逝去時(shí)間的屬性的集合,CALayer和CAAnimation都實(shí)現(xiàn)了這個(gè)協(xié)議,所以時(shí)間可以被任意基于一個(gè)圖層或者一段動(dòng)畫的類控制。
    //      速度控制函數(shù)(CAMediaTimingFunction)
    //    1.kCAMediaTimingFunctionLinear(線性):勻速,給你一個(gè)相對(duì)靜態(tài)的感覺
    //    2.kCAMediaTimingFunctionEaseIn(漸進(jìn)):動(dòng)畫緩慢進(jìn)入,然后加速離開
    //    3.kCAMediaTimingFunctionEaseOut(漸出):動(dòng)畫全速進(jìn)入,然后減速的到達(dá)目的地
    //    4.kCAMediaTimingFunctionEaseInEaseOut(漸進(jìn)漸出):動(dòng)畫緩慢的進(jìn)入,中間加速,然后減速的到達(dá)目的地。這個(gè)是默認(rèn)的動(dòng)畫行為。
    animation.duration = 6;//動(dòng)畫持續(xù)時(shí)間
    animation.beginTime = begintime;
    animation.repeatCount = MAXFLOAT;
    animation.autoreverses =false;
    animation.calculationMode = kCAAnimationCubicPaced;//自動(dòng)計(jì)算
    animation.rotationMode = kCAAnimationRotateAuto;//動(dòng)畫角度自動(dòng)調(diào)整
    [self.view.layer addSublayer:carLayer];
    [carLayer addAnimation:animation forKey:@"carAnimation"];

附上github地址歡迎Star~~~~~,至此過山車動(dòng)畫完成。。

參考文檔:CALayer中文翻譯(Swift版)

COPY原鏈接

最后編輯于
?著作權(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)容

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