前言:
关于贝塞尔曲线与CAShapeLayer的学习
学习Demo演示:
贝塞尔曲线简单了解
使用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.曲面
- (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 应届生