UIBezierPath的使用

原文链接:http://blog.csdn.net/mumubumaopao/article/details/52013319

最近研究了下UIBezierPath,虽然他的构造方法不是特别多,但是感觉还是特别实用的,就是用起来感觉很方便,其主要作用还是用于为视图的Layer层添加路径,相当于根据我们创建的path来对目标视图进行切割.比如说我要把一个视图的形状裁剪一下,或者我想自定义一个几何图形什么的,用UIBezierPath来实现都是很方便的.唯一不方便的地方就是如果要在一个view上只使用UIBezierPath来进行绘制几何图形的话,那么必须要在- (void)drawRect:(CGRect)rect方法里绘制或者调用,这样一来就给我们带来了些许的限制,所以,在日常的开发中,如果要创建自定义的几何图形的话,经常还是使用CAShapeLayer和UIBezierPath共同来创建.各位看官可以看下我的这篇博客:CAShapeLayer的使用,希望能给各位大人带来少许帮助.

不过,今天我们就事论事,只说UIBezierPath的使用,下面是我写的一个Demo,可以先看下效果

这个Demo里包括了UIBezierPath使用频率最高的几种几何图形以及创建的方法,其实UIBezierPath的使用很简单,只不过有些细节需要注意下,下面就先看一下UIBezierPath提供的构造方法(因为对UIBezierPath对象的设置很多地方都是雷同的,所以第一个构造方法我会详细讲解使用方法,后面的几个就不详细讲解了,该Demo我已经上传到github,各位看官可以去github下载完整的工程代码,包括了使用实例,链接我会在后面贴出来):

- +(instancetype)bezierPath;

该方法直接返回一个UIBezierPath对象,不需要传递任何参数,我们可以直接对创建出来的对象操作,使用方法如下:

//绘制一个三角形-(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 = [UIColorredColor];    [redColor set];    [path fill];//设置线条属性  各种格式我会贴出来给大家看,方便对比path.lineCapStyle= kCGLineJoinRound;//线段端点格式path.lineJoinStyle= kCGLineJoinRound;//线段接头格式path.lineWidth=8;//设置路径颜色  原理和设置填充颜色一样,这不过是调用[path stroke]方法来设置路径额颜色 设置线宽为8UIColor*blackColor = [UIColorblackColor];    [blackColor set];    [path stroke];}

上文提到了lineCapStyle和lineJoinStyle,这两个属性分别对应的是线条端点的风格和线条接头处的风格,有以下三个枚举值:

typedef CF_ENUM(int32_t, CGLineJoin){

kCGLineJoinMiter,

kCGLineJoinRound,

kCGLineJoinBevel

};

对应的风格如下所示:

端点处的风格:(lineCapStyle)

kCGLineJoinMiter,

kCGLineJoinBevel  这两个风格是一样的,都是直角风格如下所示:

kCGLineJoinRound,圆角风格,如下所示:

接头处的风格:(lineJoinStyle)

kCGLineJoinMiter  斜接

kCGLineJoinRound  圆角

kCGLineJoinBevel  斜角

- +(instancetype)bezierPathWithRect:(CGRect)rect;

该方法会根据传进去的CGRect结构体来创建一个矩形

+(instancetype)bezierPathWithOvalInRect:(CGRect)rect;

该方法会根据传进去的结构体(矩形)创建一个内切圆,如果该矩形是正方形的话,那么切出来的是一个圆形,如果是长方形的话,切出来的则是一个椭圆

+(instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius;

该方法会根据传进去的矩形和圆角角度创建一个四个角都是圆角的矩形

+(instancetype)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii;

参数解析:

rect: 基础矩形

corners: 选择矩形中需要添加圆角的位置,该值有四个枚举值,如下所示:

UIRectCornerTopLeft 左上方添加

UIRectCornerTopRight 右上方添加

UIRectCornerBottomLeft 左下方添加

UIRectCornerBottomRight 右下方添加

UIRectCornerAllCorners 全部添加

传值的时候,可以传进去单独的值,如:UIRectCornerTopLeft(在左上角添加圆角),可以传进去多个值,中间使用’|’隔开,如:UIRectCornerTopLeft|UIRectCornerTopRight(给左上角和右上角添加圆角)

ornerRadii:这个参数的意思是,传进去一个矩形A的宽高,以需要添加的角的顶点为矩形A的左上角,在该矩形内做内切圆,为矩形添加圆角.

+(instancetype)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;

该方法是用来绘制圆形的

参数解析:

center 圆心位置

radius 半径

startAngle 开始角度,默认从3点钟开始

endAngle 结束角度

clockwise 是否顺时针方向绘制

+(instancetype)bezierPathWithCGPath:(CGPathRef)CGPath;

该方法和第一个方法类型类似,只不过该方法传进去的是一个CGPath的路径.

关于fill的讨论

上文中提到,

Tip: 这个fill方法很有意思

如果第一次设置上下文环境为红色,那么调用fill的则会为该路径内填充红色

但是第二次设置上下文环境为绿色时,调用fill方法并不是说将路径内的红色替换掉,而是在红色的上方填充一次绿色

现在我们就来验证一下这个说法,首先,我们绘制一个圆形,代码如下,填充颜色为红色,边框颜色为黑色,线宽30:

UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(40,80, k_ScreenWidth -80, k_ScreenWidth -80)];

//设置填充颜色

UIColor*redColor = [UIColorredColor];   

 [redColor set];    [path fill];

//设置路径格式path.lineWidth=30.0;    

path.lineCapStyle= kCGLineJoinRound;   

 path.lineJoinStyle= kCGLineJoinRound;

//设置路径颜色

UIColor*blackColor = [UIColorblackColor];    [blackColor set];    [path stroke];


效果如下:

然后我们在末尾再次填充颜色,执行代码如下:

UIColor *greenColor = [UIColor greenColor];

[greenColorset];[path fill];

UIColor *greenColor = [UIColor greenColor];   

 [greenColorset];[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 = [UIColorredColor];    [redColor set];    [path fill];//设置线条属性path.lineCapStyle= kCGLineJoinRound;//线段端点格式path.lineJoinStyle= kCGLineJoinRound;//线段接头格式path.lineWidth=8;//设置路径颜色  原理和设置填充颜色一样,这不过是调用[path stroke]方法来设置路径额颜色 设置线宽为8UIColor*blackColor = [UIColorblackColor];    [blackColor set];    [path stroke];}#pragma mark:由于设置填充颜色、线条颜色、线条宽度代码重复冗余,所以将其写到一个方法里,统一设置为填充颜色为红色,线条颜色为黑色,线条宽度为8//绘制一个矩形-(void)drawRectangle{    UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(40,40,k_CurrentWidth -80, k_CurrentHeight -80)];    [selfsetPath:path];}//绘制一个实心圆形-(void)drawFillCircle{/*

该方法是使用一个矩形为基准绘制其内切圆

当该矩形是正方形时,绘制出的为圆形

当该矩形为长方形的时候,绘制出来的是椭圆

*/UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(40,80, k_ScreenWidth -80, k_ScreenWidth -80)];    [selfsetPath:path];}//绘制一个空心圆形  主要为了展示使用不同的工厂方法来创建圆形-(void)drawEmptyCircle{    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(k_ScreenWidth/2, k_CurrentHeight -300) radius:(k_ScreenWidth -40)/2startAngle:0endAngle:k_DegreesToRadians(360)                                                    clockwise:YES];//设置填充颜色UIColor*redColor = [UIColorclearColor];    [redColor set];    [path fill];//设置路径格式path.lineWidth=8;    path.lineCapStyle= kCGLineJoinRound;    path.lineJoinStyle= kCGLineJoinRound;//设置路径颜色UIColor*blackColor = [UIColorblackColor];    [blackColor set];    [path stroke];}//绘制一个四个角都是圆角额矩形-(void)drawCornerRectangle{    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(40,40,k_CurrentWidth -80, k_CurrentHeight -80)                                                    cornerRadius:20];    [selfsetPath: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)];    [selfsetPath: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 = [UIColorblackColor];    [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 = [UIColorblackColor];    [strokeColor set];    [path stroke];}-(void)setPath:(UIBezierPath*)path{//设置填充颜色UIColor*redColor = [UIColorredColor];    [redColor set];    [path fill];//设置路径格式path.lineWidth=8.0;    path.lineCapStyle= kCGLineJoinRound;    path.lineJoinStyle= kCGLineJoinRound;//设置路径颜色UIColor*blackColor = [UIColorblackColor];    [blackColor set];    [path stroke];}

加入审核被拒交流群,一起交流审核上架经验吧~~ 群号:689757099

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容