··~~~~因?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"];