iOS - 关于贝塞尔曲线与CAShapeLayer的学习

前言:
关于贝塞尔曲线与CAShapeLayer的学习

学习Demo演示:

贝塞尔学习.gif

贝塞尔曲线简单了解

使用UIBezierPath类可以创建基于矢量的路径,这个类在UIKit中。此类是Core Graphics框架关于path的一个封装。使用此类可以定义简单的形状,如椭圆或者矩形,或者有多个直线和曲线段组成的形状。

Bezier Path 基础
UIBezierPath对象是CGPathRef数据类型的封装。path如果是基于矢量形状的,都用直线和曲线段去创建。我们使用直线段去创建矩形和多边形,使用曲线段去创建弧(arc),圆或者其他复杂的曲线形状。

每一段都包括一个或者多个点,绘图命令定义如何去诠释这些点。每一个直线段或者曲线段的结束的地方是下一个的开始的地方。

每一个连接的直线或者曲线段的集合成为subpath。一个UIBezierPath对象定义一个完整的路径包括一个或者多个subpaths。

  • 创建和使用一个path对象的过程是分开的。创建path是第一步,包含一下步骤:
    (1)创建一个Bezier path对象。
    (2)使用方法moveToPoint:去设置初始线段的起点。
    (3)添加line或者curve去定义一个或者多个subpaths。
    (4)改变UIBezierPath对象跟绘图相关的属性。
    例如,我们可以设置stroked path的属性lineWidth和lineJoinStyle。也可以设置filled path的属性usesEvenOddFillRule。

当创建path,我们应该管理path上面的点相对于原点(0,0),这样我们在随后就可以很容易的移动path了。为了绘制path对象,我们要用到stroke和fill方法。这些方法在current graphic context下渲染path的line和curve段。

CAShapeLayer

- 简单介绍:
 CAShapeLayer继承自CALayer,因此,可使用CALayer的所有属性。但是,CAShapeLayer需要和贝塞尔曲线配合使用才有意义。
 #CAShapeLayer和drawRect的比较
- 1.drawRect:属于CoreGraphics框架,占用CPU,性能消耗大 
- 2.CAShapeLayer:属于CoreAnimation框架,通过GPU来渲染图形,节省性能。动画渲染直接提交给手机GPU,不消耗内存

温馨提示:drawRect只是一个方法而已,是UIView的方法,重写此方法可以完成我们的绘制图形功能。

CAShapeLayer与UIBezierPath的关系

CAShapeLayer与UIBezierPath的关系:
- 1.CAShapeLayer中shape代表形状的意思,所以需要形状才能生效
- 2.贝塞尔曲线可以创建基于矢量的路径,而UIBezierPath类是对CGPathRef的封装
- 3.贝塞尔曲线给CAShapeLayer提供路径,CAShapeLayer在提供的路径中进行渲染。路径会闭环,所以绘制出了Shape
- 4.用于CAShapeLayer的贝塞尔曲线作为path,其path是一个首尾相接的闭环的曲线,即使该贝塞尔曲线不是一个闭环的曲线


代码示例

CAShapeLayer与UIBezierPath画图

1.折线


- (IBAction)折线:(id)sender {
[self clearDisplayView];

//   创建一个路径对象
UIBezierPath *linePath = [UIBezierPath bezierPath];
//  起点
[linePath moveToPoint:(CGPoint){20,20}];
// 其他点
[linePath addLineToPoint:(CGPoint){160,160}];
[linePath addLineToPoint:(CGPoint){180,50}];
>
//  设置路径画布
CAShapeLayer *lineLayer = [CAShapeLayer layer];
lineLayer.bounds = (CGRect){0,0,200,200};
lineLayer.position = _centerPosition;
lineLayer.lineWidth = 2.0;
lineLayer.strokeColor = [UIColor orangeColor].CGColor; //   边线颜色
>
lineLayer.path = linePath.CGPath;
lineLayer.fillColor  = nil;   //  默认是black
//  添加到图层上
[self.displayView.layer addSublayer:lineLayer];
}

2. 三角形

 - (IBAction)三角形:(id)sender {
     [self clearDisplayView];
>
//  创建一个路径对象
UIBezierPath *polyonPath = [UIBezierPath bezierPath];
>
//  起点-->相对于所在视图
[polyonPath moveToPoint:(CGPoint){20,40}];
//  其他点
[polyonPath addLineToPoint:(CGPoint){160,160}];
[polyonPath addLineToPoint:(CGPoint){140,50}];
[polyonPath closePath];  // 关闭路径  添加一个结尾和起点相同的点
>
CAShapeLayer *polygonLayer = [CAShapeLayer layer];
>
polygonLayer.bounds = (CGRect){0,0,160,160};
polygonLayer.position = _centerPosition;
polygonLayer.lineWidth = 2;
polygonLayer.strokeColor = [UIColor redColor].CGColor;  //  边线的颜色
polygonLayer.path = polyonPath.CGPath;
polygonLayer.fillColor = nil;
>
[self.displayView.layer addSublayer:polygonLayer];
}

3. 多边形

 - (IBAction)多边形:(id)sender {
[self clearDisplayView];
UIBezierPath *aPath = [UIBezierPath bezierPath];
  >  
// Set the starting point of the shape.
[aPath moveToPoint:CGPointMake(100, 0.0)];
// Draw the lines
[aPath addLineToPoint:CGPointMake(200.0,40.0)];
[aPath addLineToPoint:(CGPoint){160,140}];
[aPath addLineToPoint:(CGPoint){40,140}];
[aPath addLineToPoint:(CGPoint){0,40}];
[aPath closePath];
  >  
CAShapeLayer *layer = [CAShapeLayer layer];
layer.bounds = (CGRect){0,0,200,160};
  >  
layer.position = _centerPosition;
layer.lineWidth = 2.0;
layer.lineCap = kCALineCapRound;  // 线条拐角
layer.lineJoin = kCALineCapRound;   //  终点处理
layer.strokeColor = [UIColor greenColor].CGColor;
layer.path = aPath.CGPath;
layer.fillColor = nil; // 默认为blackColor
 >  
[self.displayView.layer addSublayer:layer];
  >  
 }

4. 椭圆和圆



- (IBAction)椭圆:(id)sender {
[self clearDisplayView];

    //  创建椭圆一个路径
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:(CGRect){0,0,260,200}];
>
CAShapeLayer *pathLayer = [CAShapeLayer layer];
>
pathLayer.bounds = (CGRect){0,0,260,200};
pathLayer.position = _centerPosition;
pathLayer.lineWidth = 2.0;
pathLayer.strokeColor = [UIColor grayColor].CGColor;
pathLayer.path = path.CGPath;
pathLayer.fillColor = nil;  // 默认为blackColor
[self.displayView.layer addSublayer:pathLayer];
}



- (IBAction)圆:(id)sender {
[self clearDisplayView];

//   创建一个路径
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:(CGRect){0,0,200,200}];
>
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.bounds = (CGRect){0,0,200,200};
pathLayer.position = _centerPosition;
>
pathLayer.lineWidth = 2.0;
pathLayer.strokeColor = [UIColor orangeColor].CGColor;  //  边缘颜色
    pathLayer.path = path.CGPath;
 //    pathLayer.fillColor = nil;
 //    [self.displayView.layer addSublayer:pathLayer];
 self.displayView.layer.mask = pathLayer;  // layer 的 mask属性,添加蒙版
}

5. 实心矩形


- (IBAction)实心矩形:(id)sender {
[self clearDisplayView];
>
CAShapeLayer *layer = [CAShapeLayer layer];
layer.frame = (CGRect){0,0,100,100};
layer.position = _centerPosition;
layer.backgroundColor = [UIColor lightGrayColor].CGColor;
[self.displayView.layer addSublayer:layer];
}

6. 空心矩形


- (IBAction)空心矩形:(id)sender {
[self clearDisplayView];

UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(130, 10, 100, 80)];
>
 CAShapeLayer *layer = [CAShapeLayer layer];
//填充颜色
layer.fillColor = [UIColor clearColor].CGColor;
//边框颜色
layer.strokeColor = [UIColor blackColor].CGColor;
layer.path = path.CGPath;
[self.displayView.layer addSublayer:layer];
}

7. 画圆角矩形

- (IBAction)圆角矩形:(id)sender {
  [self clearDisplayView];
//  创建一个路径
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:(CGRect){0,0,200,200} cornerRadius:50];
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.bounds = (CGRect){0,0,200,200};
pathLayer.position = _centerPosition;
pathLayer.lineWidth = 2.0;
pathLayer.strokeColor = [UIColor redColor].CGColor;
// pathLayer.fillColor = [UIColor lightGrayColor].CGColor; // 默认为blackColor
// [polygonView.layer addSublayer:polygonLayer];
pathLayer.path = path.CGPath;
self.displayView.layer.mask = pathLayer;  // layer 的 mask属性,添加蒙版
 }

8. 画单角的圆角矩形的UIBezierPath相关方法

- (IBAction)单圆角矩形:(id)sender {
  [self clearDisplayView];
  //   创建路径
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:(CGRect){0,0,200,200} byRoundingCorners:UIRectCornerTopLeft cornerRadii:(CGSize){100,0}];
CAShapeLayer *pathLayer = [CAShapeLayer layer];
>
pathLayer.bounds = (CGRect){0,0,200,200};
pathLayer.position = _centerPosition;
pathLayer.lineWidth = 2.0;
pathLayer.strokeColor = [UIColor grayColor].CGColor;
pathLayer.path = path.CGPath;
pathLayer.fillColor = nil;
[self.displayView.layer addSublayer:pathLayer];
//    self.displayView.layer.mask = pathLayer;
}

9. 画圆弧

- (IBAction)圆弧:(id)sender {
   [self clearDisplayView];
 //   绘制路径对象
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:_centerPosition radius:50 startAngle:0 endAngle:M_PI_2 clockwise:YES];
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.lineWidth = 2.0;
pathLayer.strokeColor = [UIColor redColor].CGColor;
pathLayer.fillColor = nil;
pathLayer.path = path.CGPath;
>
[self.displayView.layer addSublayer:pathLayer];
}

10.折线和弧线构成的曲线**

  #pragma mark - 折线和弧线构成的曲线
 - (IBAction)折线弧线曲:(id)sender {
 [self clearDisplayView];
//  创建路径
UIBezierPath *path = [UIBezierPath bezierPath];
//  折线
[path moveToPoint:(CGPoint){100,100}];
[path addLineToPoint:_centerPosition];
//   添加一条弧线
[path addArcWithCenter:_centerPosition radius:50 startAngle:0 endAngle:M_PI clockwise:YES];
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.lineWidth = 2.0;
pathLayer.strokeColor = [UIColor redColor].CGColor;
pathLayer.fillColor = nil;
pathLayer.path = path.CGPath;
[self.displayView.layer addSublayer:pathLayer];
 }

11.二次贝塞尔曲线

- (IBAction)二次贝塞尔曲线:(id)sender {
 [self clearDisplayView];
 //   绿色二次贝塞尔曲线
UIBezierPath *path1 = [UIBezierPath bezierPath];
[path1 moveToPoint:(CGPoint){0,100}];
[path1 addQuadCurveToPoint:(CGPoint){200,50} controlPoint:(CGPoint){100,200}];
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.position = (CGPoint){100,100};
pathLayer.lineWidth = 2.0;
pathLayer.strokeColor = [UIColor greenColor].CGColor;
pathLayer.fillColor = nil;
pathLayer.path = path1.CGPath;
[self.displayView.layer addSublayer:pathLayer];
>
>
// 红色二次贝塞尔曲线
UIBezierPath *path2 = [UIBezierPath bezierPath];
[path2 moveToPoint:CGPointMake(0, 100)];
CGPoint end2Point = CGPointMake(100, 50);
[path2 addQuadCurveToPoint:end2Point controlPoint:CGPointMake(100, 200)]; // 二次贝塞尔曲线
CAShapeLayer *path2Layer = [CAShapeLayer layer];
path2Layer.position = (CGPoint){100,100};
path2Layer.lineWidth = 2;
path2Layer.strokeColor = [UIColor redColor].CGColor;
path2Layer.fillColor = nil; // 默认为blackColor
path2Layer.path = path2.CGPath;
[_displayView.layer addSublayer:path2Layer];
}

起点终点相同,控制点不同


总结:控制点与起点和终点所在直线偏移距离越大,曲线弧度越大。
- (IBAction)二次贝塞尔曲线2:(id)sender {
[self clearDisplayView];

CGPoint startPoint = CGPointMake(0, 100);
CGPoint endPoint = CGPointMake(200, 50);
//   绿色二次贝塞尔曲线
UIBezierPath *path1 = [UIBezierPath bezierPath];
[path1 moveToPoint:startPoint];
[path1 addQuadCurveToPoint:endPoint controlPoint:CGPointMake(100, 200)]; // 二次贝塞尔曲线
CAShapeLayer *path1Layer = [CAShapeLayer layer];
path1Layer.position = (CGPoint){100,100};
path1Layer.lineWidth = 2;
path1Layer.strokeColor = [UIColor greenColor].CGColor;
path1Layer.fillColor = nil; // 默认为blackColor
path1Layer.path = path1.CGPath;
[_displayView.layer addSublayer:path1Layer];
 // 红色二次贝塞尔曲线
UIBezierPath *path2 = [UIBezierPath bezierPath];
[path2 moveToPoint:startPoint];
[path2 addQuadCurveToPoint:endPoint controlPoint:CGPointMake(100, 150)]; // 二次贝塞尔曲线
CAShapeLayer *path2Layer = [CAShapeLayer layer];
path2Layer.position = (CGPoint){100,100};
path2Layer.lineWidth = 2;
path2Layer.strokeColor = [UIColor redColor].CGColor;
path2Layer.fillColor = nil; // 默认为blackColor
path2Layer.path = path2.CGPath;
[_displayView.layer addSublayer:path2Layer];
}

12. 三次贝塞尔曲线


- (IBAction)三次贝塞尔曲线:(id)sender {
[self clearDisplayView];

CGPoint startPoint = CGPointMake(0, 100);
CGPoint endPoint = CGPointMake(200, 100);
// 绿色二次贝塞尔曲线
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:startPoint];
[path addCurveToPoint:endPoint controlPoint1:CGPointMake(50, 75) controlPoint2:CGPointMake(150, 125)]; // 二次贝塞尔曲线
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.position = (CGPoint){100,100};
pathLayer.lineWidth = 2;
pathLayer.strokeColor = [UIColor redColor].CGColor;
pathLayer.fillColor = nil; // 默认为blackColor
pathLayer.path = path.CGPath;
[_displayView.layer addSublayer:pathLayer];
}

13. 单控制点曲线

 - (IBAction)单控制点曲线:(id)sender {
     [self clearDisplayView];
 //贝塞尔曲线的画法是由起点、终点、控制点三个参数来画的,为了解释清楚这个点,我写了几行代码来解释它
CGPoint startPoint   = CGPointMake(50, 100);
CGPoint endPoint     = CGPointMake(300, 100);
CGPoint controlPoint = CGPointMake(175, 10);
 //   红点
CALayer *layer1 = [CALayer layer];
layer1.frame = CGRectMake(startPoint.x, startPoint.y, 5, 5);
layer1.backgroundColor = [UIColor redColor].CGColor;
CALayer *layer2 = [CALayer layer];
layer2.frame = CGRectMake(endPoint.x, endPoint.y, 5, 5);
layer2.backgroundColor = [UIColor redColor].CGColor;
CALayer *layer3 = [CALayer layer];
layer3.frame = CGRectMake(controlPoint.x, controlPoint.y, 5, 5);
layer3.backgroundColor = [UIColor redColor].CGColor;
//   画线
UIBezierPath *path = [UIBezierPath bezierPath];
CAShapeLayer *layer = [CAShapeLayer layer];
[path moveToPoint:startPoint];
[path addQuadCurveToPoint:endPoint controlPoint:controlPoint];
layer.path = path.CGPath;
layer.fillColor = [UIColor clearColor].CGColor;
layer.strokeColor = [UIColor blackColor].CGColor;
[self.displayView.layer addSublayer:layer];
[self.displayView.layer addSublayer:layer1];
[self.displayView.layer addSublayer:layer2];
[self.displayView.layer addSublayer:layer3];
}

14.双控制点曲线

- (IBAction)双控制点曲线:(id)sender {
[self clearDisplayView];
//贝塞尔曲线的画法是由起点、终点、控制点三个参数来画的,为了解释清楚这个点,我写了几行代码来解释它
CGPoint startPoint   = CGPointMake(50, 70);
CGPoint endPoint     = CGPointMake(300, 70);
CGPoint controlPoint1 = CGPointMake(112.5, 10);
CGPoint controlPoint2 = CGPointMake(237.5, 130);
//   红点
CALayer *layer1 = [CALayer layer];
layer1.frame = CGRectMake(startPoint.x, startPoint.y, 5, 5);
layer1.backgroundColor = [UIColor redColor].CGColor;
>
CALayer *layer2 = [CALayer layer];
layer2.frame = CGRectMake(endPoint.x, endPoint.y, 5, 5);
layer2.backgroundColor = [UIColor redColor].CGColor;
>
CALayer *layer3 = [CALayer layer];
layer3.frame = CGRectMake(controlPoint1.x, controlPoint1.y, 5, 5);
layer3.backgroundColor = [UIColor redColor].CGColor;
>
CALayer *layer4 = [CALayer layer];
layer4.frame = CGRectMake(controlPoint2.x, controlPoint2.y, 5, 5);
layer4.backgroundColor = [UIColor redColor].CGColor;
//  画线
UIBezierPath *path = [UIBezierPath bezierPath];
CAShapeLayer *layer = [CAShapeLayer layer];
>
[path moveToPoint:startPoint];
[path addCurveToPoint:endPoint controlPoint1:controlPoint1 controlPoint2:controlPoint2];
>
layer.path = path.CGPath;
layer.fillColor = [UIColor clearColor].CGColor;
layer.strokeColor = [UIColor blackColor].CGColor;
>
[self.displayView.layer addSublayer:layer];
[self.displayView.layer addSublayer:layer1];
[self.displayView.layer addSublayer:layer2];
[self.displayView.layer addSublayer:layer3];
[self.displayView.layer addSublayer:layer4];
}

15.曲面

Paste_Image.png

- (IBAction)曲面:(id)sender {
    [self clearDisplayView];
CGSize size = self.displayView.frame.size;
CGFloat startHeight = size.height * 0.2;
CGFloat endHeight = size.height * 0.4;
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(0, startHeight)];
[path addLineToPoint:CGPointMake(0, endHeight)];
[path addLineToPoint:CGPointMake(size.width, endHeight)];
[path addLineToPoint:CGPointMake(size.width, startHeight)];
[path addQuadCurveToPoint:CGPointMake(0, startHeight) controlPoint:CGPointMake(size.width/2, 0)];
>
CAShapeLayer *layer = [CAShapeLayer layer];
layer.strokeColor = [UIColor purpleColor].CGColor;
layer.fillColor = [UIColor whiteColor].CGColor;
layer.path = path.CGPath;
[self.displayView.layer addSublayer:layer];
}

16.综合练习- 绘哆啦A梦

#pragma mark - 绘哆啦A梦
- (IBAction)btnDuoLaAMeng_Click:(id)sender
{
[self clearDisplayView];
>
CGFloat arcCenterX = self.view.frame.size.width/2;
CGFloat arcCenterY = 80;
CGFloat delay = LanPangZiDuration;
>
//头
CAShapeLayer *headLayer = [CAShapeLayer layer];
UIBezierPath *headPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(self.view.frame.size.width/2-80, 0, 160, 160) cornerRadius:80];
[self setLayer:headLayer path:headPath delay:delay*0];
>
//脸
CAShapeLayer *faceLayer = [CAShapeLayer layer];
UIBezierPath *facePath = [UIBezierPath bezierPath];
[facePath moveToPoint:CGPointMake(arcCenterX-80*sqrt(2.0)/2, arcCenterY+80*sqrt(2.0)/2)];
[facePath addCurveToPoint:CGPointMake(arcCenterX-30, arcCenterY-20) controlPoint1:CGPointMake(arcCenterX-80, arcCenterY+25) controlPoint2:CGPointMake(arcCenterX-80, arcCenterY-20)];
[facePath addLineToPoint:CGPointMake(arcCenterX+30, arcCenterY-20)];
[facePath addCurveToPoint:CGPointMake(arcCenterX+80*sqrt(2.0)/2, arcCenterY+80*sqrt(2.0)/2) controlPoint1:CGPointMake(arcCenterX+80, arcCenterY-20) controlPoint2:CGPointMake(arcCenterX+80, arcCenterY+25)];
[facePath addQuadCurveToPoint:CGPointMake(arcCenterX-80*sqrt(2.0)/2, arcCenterY+80*sqrt(2.0)/2) controlPoint:CGPointMake(arcCenterX, arcCenterY+105)];
[self setLayer:faceLayer path:facePath delay:delay*1];
//左眼
CAShapeLayer *leftEyeLayer = [CAShapeLayer layer];
UIBezierPath *leftEyePath = [UIBezierPath bezierPath];
[leftEyePath moveToPoint:CGPointMake(arcCenterX-30, arcCenterY-25)];
[leftEyePath addQuadCurveToPoint:CGPointMake(arcCenterX-15, arcCenterY-45) controlPoint:CGPointMake(arcCenterX-30, arcCenterY-45)];
[leftEyePath addQuadCurveToPoint:CGPointMake(arcCenterX, arcCenterY-25) controlPoint:CGPointMake(arcCenterX, arcCenterY-45)];
[leftEyePath addQuadCurveToPoint:CGPointMake(arcCenterX-15, arcCenterY-5) controlPoint:CGPointMake(arcCenterX, arcCenterY-5)];
[leftEyePath addQuadCurveToPoint:CGPointMake(arcCenterX-30, arcCenterY-25) controlPoint:CGPointMake(arcCenterX-30, arcCenterY-5)];
[self setLayer:leftEyeLayer path:leftEyePath delay:delay*2];
//左眼珠
CAShapeLayer *leftEyeBallLayer = [CAShapeLayer layer];
UIBezierPath *leftEyeBallPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(arcCenterX-5, arcCenterY-30) radius:2.5 startAngle:0 endAngle:2*M_PI clockwise:YES];
[self setLayer:leftEyeBallLayer path:leftEyeBallPath delay:delay*3];
>
//右眼
CAShapeLayer *rightEyeLayer = [CAShapeLayer layer];
UIBezierPath *rightEyePath = [UIBezierPath bezierPath];
[rightEyePath moveToPoint:CGPointMake(arcCenterX, arcCenterY-25)];
[rightEyePath addQuadCurveToPoint:CGPointMake(arcCenterX+15, arcCenterY-45) controlPoint:CGPointMake(arcCenterX, arcCenterY-45)];
[rightEyePath addQuadCurveToPoint:CGPointMake(arcCenterX+30, arcCenterY-25) controlPoint:CGPointMake(arcCenterX+30, arcCenterY-45)];
[rightEyePath addQuadCurveToPoint:CGPointMake(arcCenterX+15, arcCenterY-5) controlPoint:CGPointMake(arcCenterX+30, arcCenterY-5)];
[rightEyePath addQuadCurveToPoint:CGPointMake(arcCenterX, arcCenterY-25) controlPoint:CGPointMake(arcCenterX, arcCenterY-5)];
[self setLayer:rightEyeLayer path:rightEyePath delay:delay*4];
//右眼珠
CAShapeLayer *rightEyeBallLayer = [CAShapeLayer layer];
UIBezierPath *rightEyeBallPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(arcCenterX+5, arcCenterY-30) radius:2.5 startAngle:0 endAngle:2*M_PI clockwise:YES];
[self setLayer:rightEyeBallLayer path:rightEyeBallPath delay:delay*5];
>
//鼻子
CAShapeLayer *noseLayer  = [CAShapeLayer layer];
UIBezierPath *nosePath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(arcCenterX, arcCenterY) radius:10 startAngle:0 endAngle:2*M_PI clockwise:YES];
[self setLayer:noseLayer path:nosePath delay:delay*6];
//鼻子光晕
CAShapeLayer *noseHaloLayer = [CAShapeLayer layer];
UIBezierPath *noseHaloPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(arcCenterX-4, arcCenterY-5) radius:2.5 startAngle:0 endAngle:2*M_PI clockwise:YES];
[self setLayer:noseHaloLayer path:noseHaloPath delay:delay*7];
>
//嘴巴
CAShapeLayer *mouthLayer = [CAShapeLayer layer];
UIBezierPath *mouthPath = [UIBezierPath bezierPath];
[mouthPath moveToPoint:CGPointMake(arcCenterX-60, arcCenterY+25)];
[mouthPath addQuadCurveToPoint:CGPointMake(arcCenterX+60, arcCenterY+25) controlPoint:CGPointMake(arcCenterX, arcCenterY+90)];
[self setLayer:mouthLayer path:mouthPath delay:delay*8];
CAShapeLayer *mouthLayer1 = [CAShapeLayer layer];
UIBezierPath *mouthPath1 = [UIBezierPath bezierPath];
[mouthPath1 moveToPoint:CGPointMake(arcCenterX, arcCenterY+10)];
[mouthPath1 addLineToPoint:CGPointMake(arcCenterX, arcCenterY+55)];
[self setLayer:mouthLayer1 path:mouthPath1 delay:delay*9];
//胡子
[self addBeardFromPoint:CGPointMake(arcCenterX-58, arcCenterY-5) toPoint:CGPointMake(arcCenterX-15, arcCenterY+10) delay:delay*10];
[self addBeardFromPoint:CGPointMake(arcCenterX-68, arcCenterY+15) toPoint:CGPointMake(arcCenterX-15, arcCenterY+20) delay:delay*11];
[self addBeardFromPoint:CGPointMake(arcCenterX-61, arcCenterY+45) toPoint:CGPointMake(arcCenterX-15, arcCenterY+30) delay:delay*12];
[self addBeardFromPoint:CGPointMake(arcCenterX+58, arcCenterY-5) toPoint:CGPointMake(arcCenterX+15, arcCenterY+10) delay:delay*13];
[self addBeardFromPoint:CGPointMake(arcCenterX+68, arcCenterY+15) toPoint:CGPointMake(arcCenterX+15, arcCenterY+20) delay:delay*14];
[self addBeardFromPoint:CGPointMake(arcCenterX+61, arcCenterY+45) toPoint:CGPointMake(arcCenterX+15, arcCenterY+30) delay:delay*15];
//左手
CAShapeLayer *leftHandLayer = [CAShapeLayer layer];
UIBezierPath *leftHandPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(arcCenterX-95, arcCenterY+110) radius:20 startAngle:0 endAngle:2*M_PI clockwise:YES];
[self setLayer:leftHandLayer path:leftHandPath delay:delay*16];
//左胳膊
CGFloat distanceXToArcCenter = 80*cos(M_PI_2*4/9);
CGFloat distanceYToArcCenter = 80*sin(M_PI_2*4/9);
CAShapeLayer *leftArmLayer = [CAShapeLayer layer];
UIBezierPath *leftArmPath = [UIBezierPath bezierPath];
[leftArmPath moveToPoint:CGPointMake(arcCenterX-distanceXToArcCenter, arcCenterY+distanceYToArcCenter)];
[leftArmPath addLineToPoint:CGPointMake(arcCenterX-95, arcCenterY+90)];
[leftArmPath addQuadCurveToPoint:CGPointMake(arcCenterX-75, arcCenterY+110) controlPoint:CGPointMake(arcCenterX-92, arcCenterY+107)];
[leftArmPath addLineToPoint:CGPointMake(arcCenterX-distanceXToArcCenter+1.5, arcCenterY+95)];
[self setLayer:leftArmLayer path:leftArmPath delay:delay*17];
//围巾
CAShapeLayer *mufflerLayer = [CAShapeLayer layer];
UIBezierPath *mufflerPath = [UIBezierPath bezierPath];
[mufflerPath moveToPoint:CGPointMake(arcCenterX-distanceXToArcCenter, arcCenterY+distanceYToArcCenter)];
[mufflerPath addQuadCurveToPoint:CGPointMake(arcCenterX+distanceXToArcCenter, arcCenterY+distanceYToArcCenter) controlPoint:CGPointMake(arcCenterX, arcCenterY+109)];
[mufflerPath addLineToPoint:CGPointMake(arcCenterX+distanceXToArcCenter+2, arcCenterY+distanceYToArcCenter+7)];
[mufflerPath addQuadCurveToPoint:CGPointMake(arcCenterX-distanceXToArcCenter-4, arcCenterY+distanceYToArcCenter+5) controlPoint:CGPointMake(arcCenterX, arcCenterY+115)];
[mufflerPath addLineToPoint:CGPointMake(arcCenterX-distanceXToArcCenter, arcCenterY+distanceYToArcCenter)];
[self setLayer:mufflerLayer path:mufflerPath delay:delay*18];
//身体
CAShapeLayer *bodyLayer = [CAShapeLayer layer];
UIBezierPath *bodyPath = [UIBezierPath bezierPath];
[bodyPath moveToPoint:CGPointMake(arcCenterX-distanceXToArcCenter, arcCenterY+distanceYToArcCenter+7)];
[bodyPath addQuadCurveToPoint:CGPointMake(arcCenterX-distanceXToArcCenter+5, arcCenterY+150) controlPoint:CGPointMake(arcCenterX-distanceXToArcCenter+2, arcCenterY+140)];
[bodyPath addQuadCurveToPoint:CGPointMake(arcCenterX-distanceXToArcCenter+3, arcCenterY+170) controlPoint:CGPointMake(arcCenterX-distanceXToArcCenter, arcCenterY+160)];
[bodyPath addQuadCurveToPoint:CGPointMake(arcCenterX-8, arcCenterY+170) controlPoint:CGPointMake(arcCenterX-(distanceXToArcCenter+5)/2, arcCenterY+175)];
[bodyPath addQuadCurveToPoint:CGPointMake(arcCenterX+8, arcCenterY+170) controlPoint:CGPointMake(arcCenterX, arcCenterY+155)];
[bodyPath addQuadCurveToPoint:CGPointMake(arcCenterX+distanceXToArcCenter-3, arcCenterY+170) controlPoint:CGPointMake(arcCenterX+(distanceXToArcCenter+5)/2, arcCenterY+175)];
[bodyPath addQuadCurveToPoint:CGPointMake(arcCenterX+distanceXToArcCenter-5, arcCenterY+150) controlPoint:CGPointMake(arcCenterX+distanceXToArcCenter-2, arcCenterY+160)];
[bodyPath addQuadCurveToPoint:CGPointMake(arcCenterX+distanceXToArcCenter, arcCenterY+distanceYToArcCenter+8) controlPoint:CGPointMake(arcCenterX+distanceXToArcCenter-2, arcCenterY+140)];
[bodyPath addQuadCurveToPoint:CGPointMake(arcCenterX-distanceXToArcCenter, arcCenterY+distanceYToArcCenter+7) controlPoint:CGPointMake(arcCenterX, arcCenterY+115)];
[self setLayer:bodyLayer path:bodyPath delay:delay*19];
//左脚
CAShapeLayer *leftFootLayer = [CAShapeLayer layer];
UIBezierPath *leftFootPath = [UIBezierPath bezierPath];
[leftFootPath moveToPoint:CGPointMake(arcCenterX-distanceXToArcCenter+3, arcCenterY+170)];
[leftFootPath addQuadCurveToPoint:CGPointMake(arcCenterX-distanceXToArcCenter+3, arcCenterY+195) controlPoint:CGPointMake(arcCenterX-distanceXToArcCenter-20, arcCenterY+185)];
[leftFootPath addQuadCurveToPoint:CGPointMake(arcCenterX-13, arcCenterY+195) controlPoint:CGPointMake(arcCenterX-(distanceXToArcCenter+10)/2, arcCenterY+200)];
[leftFootPath addQuadCurveToPoint:CGPointMake(arcCenterX-10, arcCenterY+170) controlPoint:CGPointMake(arcCenterX+8, arcCenterY+187)];
[self setLayer:leftFootLayer path:leftFootPath delay:delay*20];
//右脚
CAShapeLayer *rightFootLayer = [CAShapeLayer layer];
UIBezierPath *rightFootPath = [UIBezierPath bezierPath];
[rightFootPath moveToPoint:CGPointMake(arcCenterX+10, arcCenterY+170)];
[rightFootPath addQuadCurveToPoint:CGPointMake(arcCenterX+15, arcCenterY+195) controlPoint:CGPointMake(arcCenterX-12, arcCenterY+185)];
[rightFootPath addQuadCurveToPoint:CGPointMake(arcCenterX+distanceXToArcCenter-5, arcCenterY+195) controlPoint:CGPointMake(arcCenterX+(distanceXToArcCenter+20)/2, arcCenterY+200)];
[rightFootPath addQuadCurveToPoint:CGPointMake(arcCenterX+distanceXToArcCenter-3, arcCenterY+170) controlPoint:CGPointMake(arcCenterX+distanceXToArcCenter+18, arcCenterY+185)];
[self setLayer:rightFootLayer path:rightFootPath delay:delay*21];
//肚子
CAShapeLayer *bellyLayer = [CAShapeLayer layer];
UIBezierPath *bellyPath = [UIBezierPath bezierPath];
[bellyPath moveToPoint:CGPointMake(arcCenterX-30, arcCenterY+80)];
[bellyPath addCurveToPoint:CGPointMake(arcCenterX-30, arcCenterY+150) controlPoint1:CGPointMake(arcCenterX-65, arcCenterY+95) controlPoint2:CGPointMake(arcCenterX-60, arcCenterY+140)];
[bellyPath addQuadCurveToPoint:CGPointMake(arcCenterX+30, arcCenterY+150) controlPoint:CGPointMake(arcCenterX, arcCenterY+160)];
[bellyPath addCurveToPoint:CGPointMake(arcCenterX+30, arcCenterY+80) controlPoint1:CGPointMake(arcCenterX+60, arcCenterY+140) controlPoint2:CGPointMake(arcCenterX+65, arcCenterY+95)];
[bellyPath addQuadCurveToPoint:CGPointMake(arcCenterX-30, arcCenterY+80) controlPoint:CGPointMake(arcCenterX, arcCenterY+92)];
[self setLayer:bellyLayer path:bellyPath delay:delay*22];
//铃铛
CAShapeLayer *bellLayer = [CAShapeLayer layer];
UIBezierPath *bellPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(arcCenterX, arcCenterY+97) radius:15 startAngle:0 endAngle:2*M_PI clockwise:YES];
[self setLayer:bellLayer path:bellPath delay:delay*23];
//铃铛上的线
CAShapeLayer *bellLineLayer = [CAShapeLayer layer];
UIBezierPath *BellLinePath = [UIBezierPath bezierPath];
[BellLinePath moveToPoint:CGPointMake(arcCenterX-(sqrt(pow(15.0, 2)-pow(5.0, 2))), arcCenterY+92)];
[BellLinePath addLineToPoint:CGPointMake(arcCenterX+(sqrt(pow(15.0, 2)-pow(5.0, 2))), arcCenterY+92)];
[BellLinePath moveToPoint:CGPointMake(arcCenterX+(sqrt(pow(15.0, 2)-pow(2.0, 2))), arcCenterY+95)];
[BellLinePath addLineToPoint:CGPointMake(arcCenterX-(sqrt(pow(15.0, 2)-pow(2.0, 2))), arcCenterY+95)];
[self setLayer:bellLineLayer path:BellLinePath delay:delay*24];
//铃铛上的小圆点
CAShapeLayer *bellCirLayer = [CAShapeLayer layer];
UIBezierPath *bellCirPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(arcCenterX, arcCenterY+102) radius:2.5 startAngle:0 endAngle:2*M_PI clockwise:YES];
[bellCirPath moveToPoint:CGPointMake(arcCenterX, arcCenterY+104.5)];
[bellCirPath addLineToPoint:CGPointMake(arcCenterX, arcCenterY+112)];
[self setLayer:bellCirLayer path:bellCirPath delay:delay*25];
//口袋
CAShapeLayer *bagLayer = [CAShapeLayer layer];
UIBezierPath *bagPath = [UIBezierPath bezierPath];
[bagPath moveToPoint:CGPointMake(arcCenterX-40, arcCenterY+112)];
[bagPath addQuadCurveToPoint:CGPointMake(arcCenterX+40, arcCenterY+112) controlPoint:CGPointMake(arcCenterX, arcCenterY+120)];
[bagPath addCurveToPoint:CGPointMake(arcCenterX-40, arcCenterY+112) controlPoint1:CGPointMake(arcCenterX+28, arcCenterY+160) controlPoint2:CGPointMake(arcCenterX-28, arcCenterY+160)];
[self setLayer:bagLayer path:bagPath delay:delay*26];
//右手
CAShapeLayer *rightHandLayer = [CAShapeLayer layer];
UIBezierPath *rightHandPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(arcCenterX+85*cos(27/180.0*M_PI), arcCenterY-85*sin(27/180.0*M_PI)) radius:20 startAngle:0 endAngle:2*M_PI clockwise:YES];
[self setLayer:rightHandLayer path:rightHandPath delay:delay*27];
//右胳膊
CAShapeLayer *rightArmLayer = [CAShapeLayer layer];
UIBezierPath *rightArmPath = [UIBezierPath bezierPath];
[rightArmPath moveToPoint:CGPointMake(arcCenterX+80*cos(13/180.0*M_PI), arcCenterY-80*sin(13/180.0*M_PI))];
[rightArmPath addQuadCurveToPoint:CGPointMake(arcCenterX+distanceXToArcCenter, arcCenterY+distanceYToArcCenter) controlPoint:CGPointMake(arcCenterX+80*cos(13/180.0*M_PI)+9, arcCenterY+20)];
[rightArmPath addLineToPoint:CGPointMake(arcCenterX+distanceXToArcCenter, arcCenterY+distanceYToArcCenter+25)];
[rightArmPath addQuadCurveToPoint:CGPointMake(arcCenterX+93*cos(15/180.0*M_PI), arcCenterY-93*sin(15/180.0*M_PI)) controlPoint:CGPointMake(arcCenterX+90*cos(13/180.0*M_PI)+15, arcCenterY+25)];
[rightArmPath addQuadCurveToPoint:CGPointMake(arcCenterX+80*cos(13/180.0*M_PI), arcCenterY-80*sin(13/180.0*M_PI)) controlPoint:CGPointMake(arcCenterX+80*cos(13/180.0*M_PI)+5, arcCenterY-93*sin(15/180.0*M_PI)+5)];
[self setLayer:rightArmLayer path:rightArmPath delay:delay*28];
>
//上色
[self setLayerColor:faceLayer color:[UIColor whiteColor] delay:delay*16];
[self setLayerColor:leftEyeLayer color:[UIColor whiteColor] delay:delay*29];
[self setLayerColor:rightEyeLayer color:[UIColor whiteColor] delay:delay*29];
[self setLayerColor:leftEyeBallLayer color:[UIColor blackColor] delay:delay*29];
[self setLayerColor:rightEyeBallLayer color:[UIColor blackColor] delay:delay*29];
[self setLayerColor:noseLayer color:[UIColor redColor] delay:delay*29];
[self setLayerColor:noseHaloLayer color:[UIColor whiteColor] delay:delay*29];
[self setLayerColor:headLayer color:[UIColor colorWithRed:21/255.0 green:159/255.0 blue:237/255.0 alpha:1] delay:delay*29];
[self setLayerColor:leftArmLayer color:[UIColor colorWithRed:21/255.0 green:159/255.0 blue:237/255.0 alpha:1] delay:delay*29];
[self setLayerColor:leftHandLayer color:[UIColor whiteColor] delay:delay*29];
[self setLayerColor:mufflerLayer color:[UIColor redColor] delay:delay*29];
[self setLayerColor:bellyLayer color:[UIColor whiteColor] delay:delay*29];
[self setLayerColor:bellLayer color:[UIColor yellowColor] delay:delay*29];
[self setLayerColor:bodyLayer color:[UIColor colorWithRed:21/255.0 green:159/255.0 blue:237/255.0 alpha:1] delay:delay*29];
[self setLayerColor:rightHandLayer color:[UIColor whiteColor] delay:delay*29];
[self setLayerColor:rightArmLayer color:[UIColor colorWithRed:21/255.0 green:159/255.0 blue:237/255.0 alpha:1] delay:delay*29];
[self performSelector:@selector(showHello) withObject:nil afterDelay:delay*29];
}
 >
- (void)addBeardFromPoint:(CGPoint)fromPoint toPoint:(CGPoint)toPoint delay:(CFTimeInterval)delay
 {
CAShapeLayer *beardLayer1 = [CAShapeLayer layer];
UIBezierPath *beardPath1 = [UIBezierPath bezierPath];
[beardPath1 moveToPoint:fromPoint];
[beardPath1 addLineToPoint:toPoint];
[self setLayer:beardLayer1 path:beardPath1 delay:delay];
 }
 - (void)setLayerColor:(CAShapeLayer *)layer color:(UIColor *)color delay:(CFTimeInterval)delay
 {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    layer.fillColor = color.CGColor;
});
 }
- (void)setLayer:(CAShapeLayer *)layer path:(UIBezierPath *)path delay:(CFTimeInterval)delay
{
layer.path = path.CGPath;
layer.fillColor = [UIColor clearColor].CGColor;
layer.strokeColor = [UIColor lightGrayColor].CGColor;
__weak typeof(self) weakSelf = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    [weakSelf.displayView.layer addSublayer:layer];
    [weakSelf addAnimation:layer duration:LanPangZiDuration];
});
}
 - (void)showHello
{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2+90, 0, 70, 30)];
label.textAlignment = NSTextAlignmentCenter;
label.textColor = [UIColor colorWithRed:21/255.0 green:159/255.0 blue:237/255.0 alpha:1];
label.text = @"Hello";
label.font = [UIFont fontWithName:@"Chalkduster" size:20];
[self.displayView addSubview:label];
>
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
animation.fromValue = @(0);
animation.toValue = @(1);
animation.duration = 0.5f;
[label.layer addAnimation:animation forKey:nil];
  }

参考:
1. iOS CAShapeLayer & UIBezierPath画线、画图
2. iOS开发 贝塞尔曲线UIBezierPath
3. iOS_贝塞尔曲线初级篇
4. iOS CAShapeLayer精讲

希望: 能遇伯乐,谋求一份工作。2016 应届生

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容