iOS CAShapeLayer & UIBezierPath画线、画图
CAShapeLayer 继承与CALayer( 主要用于设置图层的形状)
CAShapeLayer对象属性列表
属性名 | 描述 |
---|---|
path | CGPathRef 对象,图形边线路径 |
lineWidth | 边线的宽度 |
strokeColor | 边线的颜色 |
lineDashPattern | 设置边线的样式,默认为实线,该数组为一个NSNumber数组,数组中的数值依次表示虚线中,单个线的长度,和空白的长度,如:数组@[2,2,3,4] 表示 有长度为2的线,长度为2的空白,长度为3的线,长度为4的空白 不断循环后组成的虚线。如图: |
lineDashPhase | 边线样式的起始位置,即,如果lineDashPattern设置为@[2,2,3,4],lineDashPhase即为第一个长度为2的线的起始位置 |
lineCap | 线终点的样式,默认 kCALineCapButt  kCAlineCapRound  kCALineCapSquare  |
lineJoin | 线拐点处的样式,默认 kCALineJoinMiter  kCALineJoinRound  kCALineJoinBevel  |
strokeStart strokeEnd | CGFloat类型,[0,1] 表示画边线的起点和终点(即在路径上的百分比) |
fillColor | CGColorRef对象,图形填充色,默认为黑色 |
结合UIBezierPath 与 CAShapeLayer 画图
将UIBezierPath 对象 转化为CGPathRef 对象, 赋值给CAShapeLayer的path属性即可,即可画出各种线条和图形
layer.path = bezierPath.CGPath;
画折线
- 画折线的UIBezierPath相关方法
+ (instancetype)bezierPath
生成一个UIBezierPath对象, 多用于画 不规则曲线 或 多边图形
- (void)moveToPoint:(CGPoint)point
添加路径起点
- (void)addLineToPoint:(CGPoint)point
添加路径起点外的其他点
在矩形中画一条折线
- 效果图
- 代码
// 需要画线的视图
UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.view.frame) - 100, CGRectGetMidY(self.view.frame)- 100, 200, 200)];
lineView.backgroundColor = [UIColor orangeColor];
[self.view addSubview:lineView];
// 线的路径
UIBezierPath *linePath = [UIBezierPath bezierPath];
// 起点
[linePath moveToPoint:CGPointMake(20, 20)];
// 其他点
[linePath addLineToPoint:CGPointMake(160, 160)];
[linePath addLineToPoint:CGPointMake(180, 50)];
CAShapeLayer *lineLayer = [CAShapeLayer layer];
lineLayer.lineWidth = 2;
lineLayer.strokeColor = [UIColor greenColor].CGColor;
lineLayer.path = linePath.CGPath;
lineLayer.fillColor = nil; // 默认为blackColor
[lineView.layer addSublayer:lineLayer];
画多边形
- UIBezierPath相关方法
- (void)closePath
封闭曲线(连接曲线的起点和终点形成封闭曲线)
在矩形视图中画一个三角形
- 效果图
- 代码:
// 需要多边形的视图
UIView * polygonView = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.view.frame) - 100, CGRectGetMidY(self.view.frame) - 100, 200, 200)];
polygonView.backgroundColor = [UIColor orangeColor];
[self.view addSubview:polygonView];
// 线的路径
UIBezierPath *polygonPath = [UIBezierPath bezierPath];
// 这些点的位置都是相对于所在视图的
// 起点
[polygonPath moveToPoint:CGPointMake(20, 40)];
// 其他点
[polygonPath addLineToPoint:CGPointMake(160, 160)];
[polygonPath addLineToPoint:CGPointMake(140, 50)];
[polygonPath closePath]; // 添加一个结尾点和起点相同
CAShapeLayer *polygonLayer = [CAShapeLayer layer];
polygonLayer.lineWidth = 2;
polygonLayer.strokeColor = [UIColor greenColor].CGColor;
polygonLayer.path = polygonPath.CGPath;
polygonLayer.fillColor = nil; // 默认为blackColor
[polygonView.layer addSublayer:polygonLayer];
画椭圆或圆
- 画椭圆或圆的UIBezierPath相关方法
+ (instancetype)bezierPathWithOvalInRect:(CGRect)rect:
生成一个矩形的内切椭圆UIBezierPath对象,如果矩形是正方形,就为内切圆
在矩形中画内切椭圆
- 效果图
- 代码
// 需要圆视图
UIView * view = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.view.frame) - 130, CGRectGetMidY(self.view.frame) - 100, 260, 200)];
view.backgroundColor = [UIColor orangeColor];
[self.view addSubview:view];
// 线的路径
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:view.bounds];
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.lineWidth = 2;
pathLayer.strokeColor = [UIColor greenColor].CGColor;
pathLayer.path = path.CGPath;
pathLayer.fillColor = nil; // 默认为blackColor
[view.layer addSublayer:pathLayer];
在矩形中画内切圆,并把正方形切为圆
- 效果图
- 代码
UIView * view = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.view.frame) - 100, CGRectGetMidY(self.view.frame) - 100, 200, 200)];
view.backgroundColor = [UIColor orangeColor];
[self.view addSubview:view];
// 线的路径
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:view.bounds];
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.lineWidth = 2;
pathLayer.strokeColor = [UIColor greenColor].CGColor;
pathLayer.path = path.CGPath;
// [view.layer addSublayer:pathLayer];
// pathLayer.fillColor = nil; // 默认为blackColor
view.layer.mask = pathLayer; // layer 的 mask属性,添加蒙版
画圆角矩形
- 画圆角矩形的UIBezierPath相关方法
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius
生成一个自定义圆角大小的矩形UIBezierPath对象
矩形添加圆角,切为圆角矩形
- 效果图
- 代码
// 需要画圆角矩形
UIView * view = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.view.frame) - 100, CGRectGetMidY(self.view.frame) - 100, 200, 200)];
view.backgroundColor = [UIColor orangeColor];
[self.view addSubview:view];
// 线的路径
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:view.bounds cornerRadius:50];
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.lineWidth = 2;
pathLayer.strokeColor = [UIColor greenColor].CGColor;
pathLayer.path = path.CGPath;
// pathLayer.fillColor = [UIColor lightGrayColor].CGColor; // 默认为blackColor
// [polygonView.layer addSublayer:polygonLayer];
view.layer.mask = pathLayer; // layer 的 mask属性,添加蒙版
画单角的圆角矩形的UIBezierPath相关方法
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii
为矩形的某一个角添加自定义大小的圆角(当自定义的圆角大小超过矩形宽或高的一半是,自动取矩形宽或高的一半作为圆角大小)
如果想对视图单个角切圆角,和圆切圆角相同只需将UIBezierPath对象添加为mask即可。
给矩形左上角添加圆角:
- 效果图
- 代码
// 需要圆视图
UIView * view = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.view.frame) - 100, CGRectGetMidY(self.view.frame) - 100, 200, 200)];
view.backgroundColor = [UIColor orangeColor];
[self.view addSubview:view];
// 线的路径
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:UIRectCornerTopLeft cornerRadii:CGSizeMake(100, 0)];
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.lineWidth = 2;
pathLayer.strokeColor = [UIColor greenColor].CGColor;
pathLayer.fillColor = nil; // 默认为blackColor
pathLayer.path = path.CGPath;
[view.layer addSublayer:pathLayer];
画圆弧
- 画圆弧的UIBezierPath相关方法
+ (instancetype)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise
center:圆弧的中心,相对所在视图; radius:圆弧半径; startAngle:起始点的角度(相对角度坐标系0); endAngle:结束点的角度(相对角度坐标系0); clockwise:是否为顺时针方向。
- (void)addArcWithCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise
在原有的线上添加一条弧线 。center:圆弧的中心,相对所在视图; radius:圆弧半径; startAngle:起始点的角度(相对角度坐标系0); endAngle:结束点的角度(相对角度坐标系0); clockwise:是否为顺时针方向。
在矩形中画一条圆弧
- 效果图
- 代码
UIView * view = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.view.frame) - 100, CGRectGetMidY(self.view.frame) - 100, 200, 200)];
view.backgroundColor = [UIColor orangeColor];
[self.view addSubview:view];
// 线的路径
CGPoint viewCenter = CGPointMake(view.frame.size.width / 2.0, view.frame.size.height / 2.0); // 画弧的中心点,相对于view
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:viewCenter radius:50.0 startAngle:0 endAngle:M_PI_2 clockwise:YES];
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.lineWidth = 2;
pathLayer.strokeColor = [UIColor greenColor].CGColor;
pathLayer.fillColor = nil; // 默认为blackColor
pathLayer.path = path.CGPath;
[view.layer addSublayer:pathLayer];
折线和弧线构成的曲线
- 效果图
- 代码
UIView * view = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.view.frame) - 100, CGRectGetMidY(self.view.frame) - 100, 200, 200)];
view.backgroundColor = [UIColor orangeColor];
[self.view addSubview:view];
// 线的路径
CGPoint viewCenter = CGPointMake(view.frame.size.width / 2.0, view.frame.size.height / 2.0); // 画弧的中心点,相对于view
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(50, 50)];
[path addLineToPoint:CGPointMake(100, 100)];
[path addArcWithCenter:viewCenter radius:50 startAngle:0 endAngle:M_PI clockwise:YES]; // 添加一条弧线
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.lineWidth = 2;
pathLayer.strokeColor = [UIColor greenColor].CGColor;
pathLayer.fillColor = nil; // 默认为blackColor
pathLayer.path = path.CGPath;
[view.layer addSublayer:pathLayer];
二次贝塞尔曲线
- 二次贝赛尔曲线相关方法
- (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint
贝塞尔二次曲线,起点用 moveToPoint方法给出;endPoint:贝赛尔曲线终点;controlPoint:控制点;曲线是由起点趋向控制点最后到达终点(不会经过控制点)的曲线。控制点决定曲线的起始方向,起点和终点的距离决定曲线趋向控制点的程度。
设置相同起点,相同控制点,终点不同时贝赛尔曲线比较(即,起点终点距离不同)
- 效果图
- 代码
UIView * view = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.view.frame) - 100, CGRectGetMidY(self.view.frame) - 100, 200, 200)];
view.backgroundColor = [UIColor orangeColor];
[self.view addSubview:view];
// 绿色二次贝塞尔曲线
UIBezierPath *path1 = [UIBezierPath bezierPath];
[path1 moveToPoint:CGPointMake(0, 100)];
CGPoint end1Point = CGPointMake(200, 50);
[path1 addQuadCurveToPoint:end1Point controlPoint:CGPointMake(100, 200)]; // 二次贝塞尔曲线
CAShapeLayer *path1Layer = [CAShapeLayer layer];
path1Layer.lineWidth = 2;
path1Layer.strokeColor = [UIColor greenColor].CGColor;
path1Layer.fillColor = nil; // 默认为blackColor
path1Layer.path = path1.CGPath;
[view.layer addSublayer:path1Layer];
// 红色二次贝塞尔曲线
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.lineWidth = 2;
path2Layer.strokeColor = [UIColor redColor].CGColor;
path2Layer.fillColor = nil; // 默认为blackColor
path2Layer.path = path2.CGPath;
[view.layer addSublayer:path2Layer];
总结:起点和终点的距离越小,趋向控制点结束越早,趋向终点开始越早,曲线弧度越大。
起点终点相同,控制点不同
- 效果图
- 代码
UIView * view = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.view.frame) - 100, CGRectGetMidY(self.view.frame) - 100, 200, 200)];
view.backgroundColor = [UIColor orangeColor];
[self.view addSubview:view];
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.lineWidth = 2;
path1Layer.strokeColor = [UIColor greenColor].CGColor;
path1Layer.fillColor = nil; // 默认为blackColor
path1Layer.path = path1.CGPath;
[view.layer addSublayer:path1Layer];
// 红色二次贝塞尔曲线
UIBezierPath *path2 = [UIBezierPath bezierPath];
[path2 moveToPoint:startPoint];
[path2 addQuadCurveToPoint:endPoint controlPoint:CGPointMake(100, 150)]; // 二次贝塞尔曲线
CAShapeLayer *path2Layer = [CAShapeLayer layer];
path2Layer.lineWidth = 2;
path2Layer.strokeColor = [UIColor redColor].CGColor;
path2Layer.fillColor = nil; // 默认为blackColor
path2Layer.path = path2.CGPath;
[view.layer addSublayer:path2Layer];
总结:控制点与起点和终点所在直线偏移距离越大,曲线弧度越大。
三次贝塞尔曲线
- UIBezierPath相关方法
- (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2
三次贝赛尔曲线,起点用 moveToPoint方法给出;endPoint:贝赛尔曲线终点;controlPoint1:控制点1;controlPoint2:控制点2;
曲线是由起点趋向控制点1,之后趋向控制点2,最后到达终点(不会经过控制点)的曲线。在起点和终点所在直线方向上,曲线在起点和控制点1之间,趋向控制点1;在控制点2和终点之间,趋向控制点2.控制点与起点和终点所在直线的偏移影响曲线的偏移程度
- 效果图
- 代码
UIView * view = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.view.frame) - 100, CGRectGetMidY(self.view.frame) - 100, 200, 200)];
view.backgroundColor = [UIColor orangeColor];
[self.view addSubview:view];
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.lineWidth = 2;
pathLayer.strokeColor = [UIColor greenColor].CGColor;
pathLayer.fillColor = nil; // 默认为blackColor
pathLayer.path = path.CGPath;
[view.layer addSublayer:pathLayer];