最近研究了下UIBezierPath,虽然他的构造方法不是特别多,可是感受仍是特别实用的,就是用起来感受很方便,其主要做用仍是用于为视图的Layer层添加路径,至关于根据咱们建立的path来对目标视图进行切割.好比说我要把一个视图的形状裁剪一下,或者我想自定义一个几何图形什么的,用UIBezierPath来实现都是很方便的.惟一不方便的地方就是若是要在一个view上只使用UIBezierPath来进行绘制几何图形的话,那么必需要在- (void)drawRect:(CGRect)rect方法里绘制或者调用,这样一来就给咱们带来了些许的限制,因此,在平常的开发中,若是要建立自定义的几何图形的话,常常仍是使用CAShapeLayer和UIBezierPath共同来建立.各位看官能够看下个人这篇博客:CAShapeLayer的使用,但愿能给各位大人带来少量帮助.git
不过,今天咱们就事论事,只说UIBezierPath的使用,下面是我写的一个Demo,能够先看下效果github
这个Demo里包括了UIBezierPath使用频率最高的几种几何图形以及建立的方法,其实UIBezierPath的使用很简单,只不过有些细节须要注意下,下面就先看一下UIBezierPath提供的构造方法(由于对UIBezierPath对象的设置不少地方都是雷同的,因此第一个构造方法我会详细讲解使用方法,后面的几个就不详细讲解了,该Demo我已经上传到github,各位看官能够去github下载完整的工程代码,包括了使用实例,连接我会在后面贴出来):
- +(instancetype)bezierPath;
该方法直接返回一个UIBezierPath对象,不须要传递任何参数,咱们能够直接对建立出来的对象操做,使用方法以下:sql
//绘制一个三角形 -(void)drawtriangle{ //绘制一条完整路径 首先建立路径对象,接着按绘制顺序添加关键点,最后调用[path closePath]方法闭合路径 UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(40, self.frame.size.height - 40)]; [path addLineToPoint:CGPointMake(k_ScreenWidth - 40, self.frame.size.height - 40)]; [path addLineToPoint:CGPointMake(k_ScreenWidth/2, 40)]; [path closePath]; /*设置填充颜色 建立一个颜色对象以后,须要调用颜色的set方法设置上下文环境,接着调用路径的fill方法使用上下文环境中的颜色来填充 Tip: 这个fill方法颇有意思 若是第一次设置上下文环境为红色,那么调用fill的则会为该路径内填充红色 可是第二次设置上下文环境为绿色时,调用fill方法并非说将路径内的红色替换掉,而是在红色的上方填充一次绿色 我会在博客里验证,读者也可自行验证 */ UIColor *redColor = [UIColor redColor]; [redColor set]; [path fill]; //设置线条属性 各类格式我会贴出来给你们看,方便对比 path.lineCapStyle = kCGLineJoinRound; //线段端点格式 path.lineJoinStyle = kCGLineJoinRound; //线段接头格式 path.lineWidth = 8; //设置路径颜色 原理和设置填充颜色同样,这不过是调用[path stroke]方法来设置路径额颜色 设置线宽为8 UIColor *blackColor = [UIColor blackColor]; [blackColor set]; [path stroke]; }
typedef CF_ENUM(int32_t, CGLineJoin) { kCGLineJoinMiter, kCGLineJoinRound, kCGLineJoinBevel };
对应的风格以下所示:markdown
端点处的风格:(lineCapStyle) kCGLineJoinMiter, kCGLineJoinBevel 这两个风格是同样的,都是直角风格以下所示:
kCGLineJoinRound,圆角风格,以下所示:
接头处的风格:(lineJoinStyle)ui
kCGLineJoinMiter 斜接
kCGLineJoinRound 圆角
kCGLineJoinBevel 斜角
- +(instancetype)bezierPathWithRect:(CGRect)rect;
该方法会根据传进去的CGRect结构体来建立一个矩形spa
+(instancetype)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;
该方法是用来绘制圆形的
参数解析:
center 圆心位置
radius 半径
startAngle 开始角度,默认从3点钟开始
endAngle 结束角度
clockwise 是否顺时针方向绘制.net
+(instancetype)bezierPathWithCGPath:(CGPathRef)CGPath;
该方法和第一个方法类型相似,只不过该方法传进去的是一个CGPath的路径.code
关于fill的讨论
上文中提到,
Tip: 这个fill方法颇有意思
若是第一次设置上下文环境为红色,那么调用fill的则会为该路径内填充红色
可是第二次设置上下文环境为绿色时,调用fill方法并非说将路径内的红色替换掉,而是在红色的上方填充一次绿色
如今咱们就来验证一下这个说法,首先,咱们绘制一个圆形,代码以下,填充颜色为红色,边框颜色为黑色,线宽30:对象
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(40, 80, k_ScreenWidth - 80, k_ScreenWidth - 80)]; //设置填充颜色 UIColor *redColor = [UIColor redColor]; [redColor set]; [path fill]; //设置路径格式 path.lineWidth = 30.0; path.lineCapStyle = kCGLineJoinRound; path.lineJoinStyle = kCGLineJoinRound; //设置路径颜色 UIColor *blackColor = [UIColor blackColor]; [blackColor set]; [path stroke];
效果以下:blog
而后咱们在末尾再次填充颜色,执行代码以下:
UIColor *greenColor = [UIColor greenColor];
[greenColor set]; [path fill];
咱们很清楚的能够看出来,边框的宽度减小了一半,缘由就是当咱们再次调用fill方法的时候,该方法是在原有图层上又添加了一层图像.因为路径的绘制原则是向内外扩展,咱们设置的路径宽度是30,那么它就会向内扩展15向外扩展15.当咱们再次绘制图层的时候,因为是在原来的基础上填充的,那么就会将向内扩展的15个单位的路径覆盖上,就致使了咱们看到路径宽度比原来减小了一半的效果.
该工程gitHub地址,各位看官能够去下载下来运行下看看:https://github.com/TheRuningAnt/TestUIBezierPath.git
附上文件源代码(部分重要的代码):
//绘制一个三角形 该方法会详细讲述各个参数的意思及使用方法,后面的方法仅仅展现使用方法 -(void)drawtriangle{ //绘制一条完整路径 首先建立路径对象,接着按绘制顺序添加关键点,最后调用[path closePath]方法闭合路径 UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(40, self.frame.size.height - 40)]; [path addLineToPoint:CGPointMake(k_ScreenWidth - 40, self.frame.size.height - 40)]; [path addLineToPoint:CGPointMake(k_ScreenWidth/2, 40)]; [path closePath]; /*设置填充颜色 建立一个颜色对象以后,须要调用颜色的set方法设置上下文环境,接着调用路径的fill方法使用上下文环境中的颜色来填充 Tip: 这个fill方法颇有意思 若是第一次设置上下文环境为红色,那么调用fill的则会为该路径内填充红色 可是第二次设置上下文环境为绿色时,调用fill方法并非说将路径内的红色替换掉,而是在红色的上方填充一次绿色 我会在博客里验证,读者也可自行验证 */ UIColor *redColor = [UIColor redColor]; [redColor set]; [path fill]; //设置线条属性 path.lineCapStyle = kCGLineJoinRound; //线段端点格式 path.lineJoinStyle = kCGLineJoinRound; //线段接头格式 path.lineWidth = 8; //设置路径颜色 原理和设置填充颜色同样,这不过是调用[path stroke]方法来设置路径额颜色 设置线宽为8 UIColor *blackColor = [UIColor blackColor]; [blackColor set]; [path stroke]; } #pragma mark:因为设置填充颜色、线条颜色、线条宽度代码重复冗余,因此将其写到一个方法里,统一设置为填充颜色为红色,线条颜色为黑色,线条宽度为8 //绘制一个矩形 -(void)drawRectangle{ UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(40,40 ,k_CurrentWidth - 80 , k_CurrentHeight - 80)]; [self setPath:path]; } //绘制一个实心圆形 -(void)drawFillCircle{ /* 该方法是使用一个矩形为基准绘制其内切圆 当该矩形是正方形时,绘制出的为圆形 当该矩形为长方形的时候,绘制出来的是椭圆 */ UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(40, 80, k_ScreenWidth - 80, k_ScreenWidth - 80)]; [self setPath:path]; } //绘制一个空心圆形 主要为了展现使用不一样的工厂方法来建立圆形 -(void)drawEmptyCircle{ UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(k_ScreenWidth/2, k_CurrentHeight - 300) radius:(k_ScreenWidth - 40)/2 startAngle:0 endAngle:k_DegreesToRadians(360) clockwise:YES]; //设置填充颜色 UIColor *redColor = [UIColor clearColor]; [redColor set]; [path fill]; //设置路径格式 path.lineWidth = 8; path.lineCapStyle = kCGLineJoinRound; path.lineJoinStyle = kCGLineJoinRound; //设置路径颜色 UIColor *blackColor = [UIColor blackColor]; [blackColor set]; [path stroke]; } //绘制一个四个角都是圆角额矩形 -(void)drawCornerRectangle{ UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(40,40 ,k_CurrentWidth - 80 , k_CurrentHeight - 80) cornerRadius:20]; [self setPath:path]; } //绘制一个可选角度的矩形 -(void)drawRectWithLeftAndRightCorner{ /* 参数解析: bezierPathWithRoundedRect 绘制矩形的大小 byRoundingCorners 有哪几个角须要绘制 cornerRadii 圆角角度,使用角的顶点做为圆心来切圆角 */ UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(40,40 ,k_CurrentWidth - 80 , k_CurrentHeight - 80) byRoundingCorners:UIRectCornerTopLeft|UIRectCornerTopRight cornerRadii:CGSizeMake((k_CurrentWidth - 80)/2, (k_CurrentWidth - 80)/2)]; [self setPath:path]; } - (void)drawSecondBezierPath { UIBezierPath *path = [UIBezierPath bezierPath]; //设置一个起始点 [path moveToPoint:CGPointMake(20, self.frame.size.height - 100)]; // 添加二次曲线 [path addQuadCurveToPoint:CGPointMake(self.frame.size.width - 20, self.frame.size.height - 100) controlPoint:CGPointMake(self.frame.size.width / 2, 0)]; path.lineCapStyle = kCGLineJoinBevel; path.lineJoinStyle = kCGLineJoinRound; path.lineWidth = 8.0; UIColor *strokeColor = [UIColor blackColor]; [strokeColor set]; [path stroke]; } - (void)drawThirdBezierPath { UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:CGPointMake(20, 200)]; [path addCurveToPoint:CGPointMake(300, 200) controlPoint1:CGPointMake(160, 50) controlPoint2:CGPointMake(160, 300)]; path.lineCapStyle = kCGLineCapRound; path.lineJoinStyle = kCGLineJoinRound; path.lineWidth = 5.0; UIColor *strokeColor = [UIColor blackColor]; [strokeColor set]; [path stroke]; } -(void)setPath:(UIBezierPath*)path{ //设置填充颜色 UIColor *redColor = [UIColor redColor]; [redColor set]; [path fill]; //设置路径格式 path.lineWidth = 8.0; path.lineCapStyle = kCGLineJoinRound; path.lineJoinStyle = kCGLineJoinRound; //设置路径颜色 UIColor *blackColor = [UIColor blackColor]; [blackColor set]; [path stroke]; }