UIBezierPath主要用来绘制矢量图形,它是基于Core Graphics对CGPathRef数据类型和path绘图属性的一个封装。使用UIBezierPath可以定义简单的形状。
1、UIBezierPath的属性
1. CGPath:将UIBezierPath类转换成CGPath,类似于UIColor的CGColor
2. currentPoint:当前path的位置,可以理解为path的终点
3. lineWidth:path宽度
4. lineCapStyle:path端点样式枚举,有3种样式
kCGLineCapButt, // 无端点
kCGLineCapRound, // 圆形端点
kCGLineCapSquare // 方形端点(样式上和kCGLineCapButt是一样的,但是比kCGLineCapButt长一点)
5. lineJoinStyle:拐角样式枚举,有3种样式
kCGLineJoinMiter, // 尖角
kCGLineJoinRound, // 圆角
kCGLineJoinBevel // 缺角
6.miterLimit:最大斜接长度(只有在使用kCGLineJoinMiter是才有效),边角的角度越小,斜接长度就会越大
为了避免斜接长度过长,使用lineLimit属性限制
如果斜接长度超过miterLimit,边角就会以KCALineJoinBevel类型来显示
2、UIBezierPath与Quartz2D
即UIBezierPath在drawRect中的使用,在实际中,我们多使用UIBezierPath来自定义视图。
矩形
- (void)drawRect:(CGRect)rect {
CGFloat lineWidth = 3;
//矩形(第一种方式)
UIBezierPath *rectPath = [UIBezierPath bezierPathWithRect:CGRectMake(10, 10, 50,50 )];
rectPath.lineWidth = lineWidth*2;
rectPath.lineCapStyle = kCGLineCapRound;
rectPath.lineJoinStyle = kCGLineJoinRound;
//闭合路径
[rectPath closePath];
[[UIColor greenColor] set];
//绘制边缘
[rectPath stroke];
//矩形(第二种方式)
CGContextRef ctx = UIGraphicsGetCurrentContext();
UIBezierPath *pathRect = [UIBezierPath bezierPathWithRect:CGRectMake(70, 10, 50,50 )];
CGContextAddPath(ctx, pathRect.CGPath);
[[UIColor purpleColor] set];
CGContextFillPath(ctx);
}
圆/弧
- (void)drawRect:(CGRect)rect {
CGFloat lineWidth = 3;
CGContextRef ctx = UIGraphicsGetCurrentContext();
//矩形圆
UIBezierPath *roundPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(130, 10, 50, 50) cornerRadius:10];
CGContextAddPath(ctx, roundPath.CGPath);
CGContextSetLineWidth(ctx, lineWidth);
[[UIColor orangeColor] set];
CGContextStrokePath(ctx);
//实心圆
UIBezierPath *arcPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(35, 95) radius:25 startAngle:0 endAngle:M_PI*2 clockwise:NO];
[arcPath addLineToPoint:CGPointMake(35, 95)];
[arcPath closePath];
[[UIColor brownColor] set];
[arcPath fill];
CGContextSetRGBStrokeColor(ctx, 1, 0, 0, 1);
//空心圆
/*
* clockwise 1为顺时针 0为逆时针
* 顺时针的理解:指定1创建顺时针弧或0创建逆时针弧(startAngle为0时为逆时针弧,非0为顺时针弧)
*/
UIBezierPath *arcKPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(155, 95) radius:25 startAngle:M_PI_2 endAngle:M_PI clockwise:NO];
CGContextAddPath(ctx, arcKPath.CGPath);
CGContextSetLineWidth(ctx, lineWidth);
[[UIColor lightGrayColor] set];
CGContextStrokePath(ctx);
float angle = 0;
CGPoint center = CGPointMake(150, 160);
for (int index = 1; index < 5; index++) {
CGFloat startAngle = angle;
CGFloat endAngle = index*M_PI_2;
//实心圆
UIBezierPath *arcPath = [UIBezierPath bezierPathWithArcCenter:center radius:30 startAngle:startAngle endAngle:endAngle clockwise:YES];
[arcPath addLineToPoint:center];
[arcPath closePath];
[[self randColor] set];
[arcPath fill];
angle = endAngle;
}
}
- (UIColor *)randColor
{
//rand(),就返回一个类型为int的整数,其范围是0到RAND_MAX
float red = rand() / (float)RAND_MAX;
float green = rand() / (float)RAND_MAX;
float blue = rand() / (float)RAND_MAX;
return [UIColor colorWithRed:red green:green blue:blue alpha:1];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self setNeedsDisplay];
}
线条
- (void)drawRect:(CGRect)rect {
CGFloat lineWidth = 3;
CGContextRef ctx = UIGraphicsGetCurrentContext();
//线条
UIBezierPath *linePath = [UIBezierPath bezierPath];
[linePath moveToPoint:CGPointMake(10, 130)];
[linePath addLineToPoint:CGPointMake(60, 190)];
[linePath moveToPoint:CGPointMake(60, 130)];
[linePath addLineToPoint:CGPointMake(10, 190)];
CGContextAddPath(ctx, linePath.CGPath);
CGContextSetLineWidth(ctx, lineWidth*3);
CGContextSetLineCap(ctx, kCGLineCapSquare);
CGContextSetLineJoin(ctx, kCGLineJoinBevel);
[[UIColor blackColor] set];
CGContextStrokePath(ctx);
}
效果
曲线
- (void)drawRect:(CGRect)rect {
//1.获取跟View相关联的上下文.】
CGContextRef ctx = UIGraphicsGetCurrentContext();
//2.描述路径
UIBezierPath *path = [UIBezierPath bezierPath];
//画曲线,设置起点.还有一个控制点(用来控制曲线的方向跟弯曲程度)
//设置起点
//A: CGPointMake(10, 150)
[path moveToPoint:CGPointMake(10, 150)];
//添加一要曲线到某个点
//C:CGPointMake(200, 150) B:CGPointMake(150, 10)
[path addQuadCurveToPoint:CGPointMake(200, 150) controlPoint:CGPointMake(150, 10)];
//3.把路径添加到上下文当中
CGContextAddPath(ctx, path.CGPath);
//4.把上下文的内容渲染View上
CGContextStrokePath(ctx);
}
2、UIBezierPath与CAShapeLayer
UIBezierPath与CAShapeLayer的结合,是我们开发中最常见的,功能很强大。
CAShapeLayer与UIBezierPath的关系:
CAShapeLayer中shape代表形状的意思,所以需要形状才能生效
贝塞尔曲线可以创建基于矢量的路径,而UIBezierPath类是对CGPathRef的封装
贝塞尔曲线给CAShapeLayer提供路径,CAShapeLayer在提供的路径中进行渲染。路径会闭环,所以绘制出了Shape
用于CAShapeLayer的贝塞尔曲线作为path,其path是一个首尾相接的闭环的曲线,即使该贝塞尔曲线不是一个闭环的曲线
例如设置圆角:
- (void)setFillet
{
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
imageView.image = [UIImage imageNamed:@"test"];
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:imageView.bounds byRoundingCorners:UIRectCornerAllCorners cornerRadii:imageView.bounds.size];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc]init];
//设置大小
maskLayer.frame = imageView.bounds;
//设置图形样子
maskLayer.path = maskPath.CGPath;
imageView.layer.mask = maskLayer;
}
自定义视图
- (void)addCustomizeView
{
CGFloat H = self.view.frame.size.height;
CGFloat W = self.view.frame.size.width;
CGFloat layerHeight = self.view.frame.size.height * 0.1;
UIBezierPath *bezier = [UIBezierPath bezierPath];
[bezier moveToPoint:CGPointMake(0, H-layerHeight)];
[bezier addLineToPoint:(CGPointMake(0, H - 1))];
[bezier addLineToPoint:(CGPointMake(W, H - 1))];
[bezier addLineToPoint:CGPointMake(W, H-layerHeight)];
[bezier addQuadCurveToPoint:CGPointMake(0, H-layerHeight) controlPoint:CGPointMake(W/2, H-layerHeight-40)];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.lineWidth = 3;
shapeLayer.path = bezier.CGPath;
shapeLayer.fillColor = [UIColor grayColor].CGColor;
shapeLayer.strokeColor = [UIColor greenColor].CGColor;
[self.view.layer addSublayer:shapeLayer];
}
效果