iOS中CALayer和CoreAnimal以例說教

UIKit中咱們使用的UIView、UILabel等控件其實顯示的載體都是CALayer及其子類,好比CATextLayer、CAScrollLayer等。咱們在作Layer層動畫的時候則使用的CAShapeLayer比較多。經過CoreAnimal中的CABasicAnimation結合path來實現。git

以前都是經過長篇幅的介紹一些理論知識,此次經過一個個的小案例,由簡到繁一步步介紹。github

畫正方形、圓形、半圓形等

//    UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(50, 50, 100, 100)];
//    UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(50, 50, 100, 120)];//當寬高同樣的時候就是圓,不然就是橢圓
//    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(50, 50, 100, 120) cornerRadius:90];//首先是畫一個矩形,而後再設置四個角的角度
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(100, 100) radius:80 startAngle:-M_PI_2 endAngle:M_PI/2 clockwise:YES];//以point爲中心,radius的值爲半徑畫弧。此弧的開始角度爲startAngle,結束角度爲endAngle,這兩個數值是弧度,不是角度。clockwise是畫此弧是按照順時針仍是逆時針
CAShapeLayer *pointLayer = [CAShapeLayer layer];
pointLayer.path = path.CGPath;
pointLayer.strokeColor = [[UIColor redColor] CGColor];//線條顏色
pointLayer.lineWidth = 10;
//    kCALineCapButt 直角
//    kCALineCapRound 圓角
//    kCALineCapSquare 與kCGLineCapButt是同樣的,可是比kCGLineCapButt長一點
pointLayer.lineCap = kCALineCapRound;//當線條是單獨的沒有與其餘線鏈接的時候,此時線頭的形狀
[self.view.layer addSublayer:pointLayer];
複製代碼

strokeStart和strokeEnd屬性案例

UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(100, 200) radius:80 startAngle:-M_PI_2 endAngle:M_PI*3/2 clockwise:YES];
CAShapeLayer *layer = [CAShapeLayer layer];
layer.lineWidth = 10;
layer.path = path.CGPath;
layer.strokeColor = [UIColor purpleColor].CGColor;
layer.fillColor = [UIColor orangeColor].CGColor;
layer.strokeStart = 0.5;
layer.strokeEnd = 0.8;
[self.view.layer addSublayer:layer];
複製代碼

IMG_0160.jpg
strokeStart和strokeEnd就是筆的開始和結束,值的範圍是0到1。

漸變層的使用

CAGradientLayer *layer = [CAGradientLayer layer];
layer.frame = CGRectMake(100, 300, 20, 100);
UIColor *middleColor = [UIColor colorWithWhite:255/255 alpha:0.8];
NSArray *colors = @[
                    (__bridge id)[UIColor redColor].CGColor,
                    (__bridge id)middleColor.CGColor,
                    (__bridge id)[UIColor redColor].CGColor
                    ];
layer.colors = colors;
[self.view.layer addSublayer:layer];
layer.startPoint = CGPointMake(0, 0);
layer.endPoint = CGPointMake(1, 0);
[self.view.layer addSublayer:layer];
複製代碼

IMG_0161.jpg

  • frame 漸變層是不支持路徑的,是經過frame屬性來設置大小的,只有長方形和正方形。
  • colors 設置須要漸變的顏色
  • startPoint 設置漸變的開始位置,x、y值的範圍是0到1
  • endPoint 設置漸變結束的位置,x、y值的範圍是0到1

假設咱們想經過路徑漸變應該怎麼辦呢?好比一個半圓弧的漸變(能夠思考一下怎麼實現,下邊會有實現的)bash

遮罩層

如下代碼是首先畫了一個正方形,填充顏色是紅色,而後畫了一個圓形。圓形是正方形的遮罩層 若是你們瞭解ps的話,其實遮罩層就是ps中的蒙版的概念。 遮罩層不會顯示出來,遮罩層有顏色的區域纔會將被遮罩層顯示出來,沒有顏色的不會顯示出來app

UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 100, 100) cornerRadius:50];//圓形
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = CGRectMake(0, 0, 100, 100);
maskLayer.path = maskPath.CGPath;

UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 100, 100)];//正方形
CAShapeLayer *layer = [CAShapeLayer layer];
layer.frame = CGRectMake(50, 50, 100, 100);
layer.path = path.CGPath;
layer.fillColor = [UIColor redColor].CGColor;
layer.mask = maskLayer;//設置遮罩層
[self.view.layer addSublayer:layer];
複製代碼

IMG_0162.jpg

上邊的問題不知道你們有沒有思路了呢?測試

fillRule中kCAFillRuleEvenOdd屬性

UIBezierPath *path1 = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 100, 100)];//正方形
UIBezierPath *path2 = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 100, 100) cornerRadius:50];//圓形
[path1 appendPath:path2];//結合兩個路徑
CAShapeLayer *shapLayer = [CAShapeLayer layer];
shapLayer.frame = CGRectMake(50, 50, 100, 100);
shapLayer.fillColor = [UIColor blackColor].CGColor;
shapLayer.fillRule = kCAFillRuleEvenOdd;
shapLayer.path = path1.CGPath;
shapLayer.lineWidth = 0.5;


[self.view.layer addSublayer:shapLayer];

CAShapeLayer *layer = [CAShapeLayer layer];
layer.frame = CGRectMake(50, 50, 100, 100);
layer.fillColor = [UIColor redColor].CGColor;
layer.path= path1.CGPath;
[self.view.layer insertSublayer:layer below:shapLayer];//設置一個背景,這樣看的效果更好一些
複製代碼

IMG_0163.jpg
不知道你們看效果圖有沒有明白這個屬性的做用呢?其實就是對於兩個path有重疊部分,取其非交集。好比一個矩形中有一個圓,則填充顏色的區域是這兩個的非交集部分。好比咱們畫兩個同心圓,一大一小,則可以實現畫出一個扇形。

綜合以上屬性,比較複雜的效果

UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(100, 100) radius:80 startAngle:-M_PI_2 endAngle:M_PI/2 clockwise:YES];//以point爲中心,radius的值爲半徑畫弧。此弧的開始角度爲startAngle,結束角度爲endAngle,這兩個數值是弧度,不是角度。clockwise是畫此弧是按照順時針仍是逆時針
   CAShapeLayer *pointLayer = [CAShapeLayer layer];
   pointLayer.path = path.CGPath;
   pointLayer.strokeColor = [[UIColor blackColor] CGColor];//線條顏色


   //    kCAFillModeRemoved 這個是默認值,也就是說當動畫開始前和動畫結束後,動畫對layer都沒有影響,動畫結束後,layer會恢復到以前的狀態(能夠理解爲動畫執行完成後移除)
   //    kCAFillModeForwards 當動畫結束後,layer會一直保持着動畫最後的狀態與CABasicAnimation的removedOnCompletion結合使用
   //    kCAFillModeBackwards 當在動畫開始前,你只要把layer加入到一個動畫中,layer便當即進入動畫的初始狀態並等待動畫開始.你能夠這樣設定測試代碼,延遲3秒讓動畫開始,只要動畫被加入了layer,layer便處於動畫初始狀態
   //    pointLayer.fillMode = kCAFillModeBackwards;//是針對動畫的,決定當前對象在非active時間段的行爲.好比動畫開始以前,動畫結束以後的狀態


   pointLayer.fillRule = kCAFillRuleEvenOdd;//對於兩個path有重疊部分,取其非交集。好比一個矩形中有一個圓,則填充顏色的區域是這兩個的非交集部分


   //    kCALineCapButt 直角
   //    kCALineCapRound 圓角
   //    kCALineCapSquare 與kCGLineCapButt是同樣的,可是比kCGLineCapButt長一點
   pointLayer.lineCap = kCALineCapRound;//當線條是單獨的沒有與其餘線鏈接的時候,此時線頭的形狀

   //    kCALineJoinMiter 正常鏈接
   //    kCALineJoinRound 圓角
   //    kCALineJoinBevel 成斜角,是一條斜線
   //    pointLayer.lineJoin = kCALineJoinRound;//當線條與其餘線有鏈接的時候,鏈接處最外側線的顯示方式
   pointLayer.fillColor = [UIColor clearColor].CGColor;//填充顏色。這裏由於是遮罩層,因此設置爲無顏色,則這部分不會顯示出來
   pointLayer.lineWidth = 10;


   CASpringAnimation *anim2 = [CASpringAnimation animationWithKeyPath:@"strokeEnd"];//9.0以後纔有的阻尼回彈動畫
   anim2.fromValue = @0;
   anim2.toValue = @1;
   anim2.duration = 2;
   anim2.timingFunction =
   [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
   anim2.damping = 8;//阻尼係數,值越大中止的越快
   anim2.stiffness =100;//剛度係數(勁度係數/彈性係數),剛度係數越大,形變產生的力就越大,運動越快
   anim2.mass = 2;//質量,影響圖層運動時的彈簧慣性,質量越大,彈簧拉伸和壓縮的幅度越大

   //initialVelocity:
   //    初始速率,動畫視圖的初始速度大小
   //    速率爲正數時,速度方向與運動方向一致,速率爲負數時,速度方向與運動方向相反

   CAGradientLayer *gradientLayer = [CAGradientLayer layer];
   gradientLayer.frame =CGRectMake(10, 10, 190, 190);
   UIColor *middleColor = [UIColor blueColor];
   NSArray *colors = @[
                       (__bridge id)[UIColor redColor].CGColor,
                       (__bridge id)middleColor.CGColor,
                       ];
   gradientLayer.colors = colors;
   gradientLayer.startPoint =  CGPointMake(0.5, 0.5);
   gradientLayer.endPoint = CGPointMake(0.5, 1);
   gradientLayer.mask = pointLayer;//設置漸變層的遮罩層爲咱們前邊畫的半弧,則只會顯示板湖那部分區域

   [self.view.layer addSublayer:gradientLayer];
   [pointLayer addAnimation:anim2 forKey:@"animal"];
複製代碼

動畫.gif

源碼

歡迎你們star來支持哦 Github源碼動畫

博客

FlyOceanFishspa

相關文章
相關標籤/搜索