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

forcamera 4年前
   <p><strong>前言:</strong></p>    <p>关于贝塞尔曲线与CAShapeLayer的学习</p>    <p>学习Demo演示:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/831e817277b31f78a6f4abbff008404a.gif"></p>    <p><strong>贝塞尔曲线简单了解</strong></p>    <p>使用UIBezierPath类可以创建基于矢量的路径,这个类在UIKit中。此类是Core Graphics框架关于path的一个封装。使用此类可以定义简单的形状,如椭圆或者矩形,或者有多个直线和曲线段组成的形状。</p>    <p><strong>Bezier Path 基础</strong></p>    <p>UIBezierPath对象是CGPathRef数据类型的封装。path如果是基于矢量形状的,都用直线和曲线段去创建。我们使用直线段去创建矩形和多边形,使用曲线段去创建弧(arc),圆或者其他复杂的曲线形状。</p>    <p>每一段都包括一个或者多个点,绘图命令定义如何去诠释这些点。每一个直线段或者曲线段的结束的地方是下一个的开始的地方。</p>    <p>每一个连接的直线或者曲线段的集合成为subpath。一个UIBezierPath对象定义一个完整的路径包括一个或者多个subpaths。</p>    <ul>     <li> <p>创建和使用一个path对象的过程是分开的。创建path是第一步,包含一下步骤:</p> <pre>  <code class="language-objectivec">(1)创建一个Bezier path对象。  (2)使用方法moveToPoint:去设置初始线段的起点。  (3)添加line或者curve去定义一个或者多个subpaths。  (4)改变UIBezierPath对象跟绘图相关的属性。</code></pre> <p>例如,我们可以设置stroked path的属性lineWidth和lineJoinStyle。也可以设置filled path的属性usesEvenOddFillRule。</p> <p>当创建path,我们应该管理path上面的点相对于原点(0,0),这样我们在随后就可以很容易的移动path了。为了绘制path对象,我们要用到stroke和fill方法。这些方法在current graphic context下渲染path的line和curve段。</p> </li>    </ul>    <p><strong>CAShapeLayer</strong></p>    <pre>  <code class="language-objectivec">- 简单介绍:   CAShapeLayer继承自CALayer,因此,可使用CALayer的所有属性。但是,CAShapeLayer需要和贝塞尔曲线配合使用才有意义。     #CAShapeLayer和drawRect的比较  - 1.drawRect:属于CoreGraphics框架,占用CPU,性能消耗大   - 2.CAShapeLayer:属于CoreAnimation框架,通过GPU来渲染图形,节省性能。动画渲染直接提交给手机GPU,不消耗内存</code></pre>    <p>温馨提示:drawRect只是一个方法而已,是UIView的方法,重写此方法可以完成我们的绘制图形功能。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/07c14ad856f2c5b96ee0192eae4f2782.png"></p>    <p>CAShapeLayer与UIBezierPath的关系</p>    <pre>  <code class="language-objectivec">- 1.CAShapeLayer中shape代表形状的意思,所以需要形状才能生效  - 2.贝塞尔曲线可以创建基于矢量的路径,而UIBezierPath类是对CGPathRef的封装  - 3.贝塞尔曲线给CAShapeLayer提供路径,CAShapeLayer在提供的路径中进行渲染。路径会闭环,所以绘制出了Shape  - 4.用于CAShapeLayer的贝塞尔曲线作为path,其path是一个首尾相接的闭环的曲线,即使该贝塞尔曲线不是一个闭环的曲线</code></pre>    <p style="text-align:center"><img src="https://simg.open-open.com/show/8fedc38ba8f0bc50792452f1d9662139.png"></p>    <p>代码示例</p>    <p>CAShapeLayer与UIBezierPath画图</p>    <p><strong>1.折线</strong></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/5e0339a079dd36454149bb0b80416d78.png"></p>    <pre>  <code class="language-objectivec">- (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];    }</code></pre>    <p><strong>2. 三角形</strong></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/8965a9dccbcfdf265133a73bad4ae0c4.png"></p>    <pre>  <code class="language-objectivec">- (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];  }</code></pre>    <p><strong>3. 多边形</strong></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/6e225d6c1433d92467569146f0d05d8b.png"></p>    <pre>  <code class="language-objectivec">- (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];     }</code></pre>    <p><strong>4. 椭圆和圆</strong></p>    <p><img src="https://simg.open-open.com/show/89876fe3a1003c35b1c087d499b841a7.png"></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/055772f4a10d3cc23bd97e540b55b400.png"></p>    <pre>  <code class="language-objectivec">- (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];    }</code></pre>    <p>圆</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/3c9ed863ad9cde493ed53ccc0b521502.png"></p>    <pre>  <code class="language-objectivec">- (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属性,添加蒙版  }</code></pre>    <p><strong>5. 实心矩形</strong></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/44b7bf746640c2451757d3f68146c801.png"></p>    <pre>  <code class="language-objectivec">- (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];   }</code></pre>    <p><strong>6. 空心矩形</strong></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/d3ac32b43b7e46eb6ed24e7a5a337684.png"></p>    <pre>  <code class="language-objectivec">- (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];    }</code></pre>    <p><strong>7. 画圆角矩形</strong></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/cd83c15dae7ac3ef4e6d572b227c5e74.png"></p>    <pre>  <code class="language-objectivec">- (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属性,添加蒙版   }</code></pre>    <p><strong>8. 画单角的圆角矩形的UIBezierPath相关方法</strong></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/0966bf0e29e536cf3283d167917947a1.png"></p>    <p> </p>    <pre>  <code class="language-objectivec">- (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;  }</code></pre>    <p><strong>9. 画圆弧</strong></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/3e3e4016405bf87c8736ce19410e45dc.png"></p>    <pre>  <code class="language-objectivec">- (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];  }</code></pre>    <p><strong>10.折线和弧线构成的曲线**</strong></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/b60a9f87ea1d346c4c4045f0578f827a.png"></p>    <pre>  <code class="language-objectivec">#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];     }</code></pre>    <p><strong>11.二次贝塞尔曲线</strong></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/3a393d21955dc1b7e24f321b3bfb62c4.png"></p>    <pre>  <code class="language-objectivec">- (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];    }</code></pre>    <p>起点终点相同,控制点不同</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/41fb8428ea05db256a9e1510ca05d048.png"></p>    <p>总结:控制点与起点和终点所在直线偏移距离越大,曲线弧度越大。</p>    <pre>  <code class="language-objectivec">- (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];    }</code></pre>    <p><strong>12. 三次贝塞尔曲线</strong></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/fc086741656b38f120c6b6968b30b15f.png"></p>    <pre>  <code class="language-objectivec">- (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];  }</code></pre>    <p><strong>13. 单控制点曲线</strong></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/b1f024994740d8cca01e09f34ae12224.png"></p>    <pre>  <code class="language-objectivec">- (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];    }</code></pre>    <p><strong>14.双控制点曲线</strong></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/442ba7f45e9d61e4b0196ce88b056ef9.png"></p>    <pre>  <code class="language-objectivec">- (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];    }</code></pre>    <p><strong>15.曲面</strong></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/ec391fc74aeeb5f38bfe956eb287921e.png"></p>    <p> </p>    <p> </p>    <pre>  <code class="language-objectivec">- (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];  }</code></pre>    <p><strong>16.综合练习- 绘哆啦A梦</strong></p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/c898253aa2a0be6a7646ab42e9a393ea.png"></p>    <pre>  <code class="language-objectivec">#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];    }</code></pre>    <p><strong>参考:</strong></p>    <pre>  <code class="language-objectivec">1. [iOS CAShapeLayer & UIBezierPath画线、画图](http://www.cnblogs.com/jaesun/p/iOS-CAShapeLayerUIBezierPath-hua-xian.html)   2. [iOS开发 贝塞尔曲线UIBezierPath](http://www.cnblogs.com/ioshe/p/5481827.html)   3. [iOS_贝塞尔曲线初级篇](http://blog.csdn.net/qq_16437739/article/details/53284064)   4. [iOS CAShapeLayer精讲](http://www.jianshu.com/p/5f08035056f6)</code></pre>    <p> </p>    <p> </p>    <p>来自:http://www.jianshu.com/p/b1c38a3a67a9</p>    <p> </p>