使用UIBezierPath类可以创建基于矢量的路径,这个类在UIKit中。此类是Core Graphics框架关于path的一个封装。使用此类可以定义简单的形状,如椭圆或者矩形,或者有多个直线和曲线段组成的形状。

Bezier Path 基础     UIBezierPath对象是CGPathRef数据类型的封装。path如果是基于矢量形状的,都用直线和曲线段去创建。我们使用直线段去创建矩形和多边形,使用曲线段去创建弧(arc),圆或者其他复杂的曲线形状。每一段都包括一个或者多个点,绘图命令定义如何去诠释这些点。每一个直线段或者曲线段的结束的地方是下一个的开始的地方。每一个连接的直线或者曲线段的集合成为subpath。一个UIBezierPath对象定义一个完整的路径包括一个或者多个subpaths。 
UIBezierPath类头文件定义

// 根据一个Rect 画一个矩形曲线

+ (instancetype)bezierPath;

/**

*  根据一个Rect 画一个椭圆曲线  Rect为正方形时 画的是一个圆

*  @param rect CGRect一个矩形

*/

+ (instancetype)bezierPathWithRect:(CGRect)rect;

/**

*  根据一个Rect 画一个圆角矩形曲线 (Radius:圆角半径)    当Rect为正方形时且Radius等于边长一半时 画的是一个圆

*  @param rect CGRect一个矩形

*/

+ (instancetype)bezierPathWithOvalInRect:(CGRect)rect;

/**

*  根据一个Rect 画一个圆角矩形曲线   当Rect为正方形时且Radius等于边长一半时 画的是一个圆

*  @param rect         CGRect一个矩形

*  @param cornerRadius 圆角半径

*/

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

typedef NS_OPTIONS(NSUInteger, UIRectCorner) {

UIRectCornerTopLeft     = 1 << 0,

UIRectCornerTopRight    = 1 << 1,

UIRectCornerBottomLeft  = 1 << 2,

UIRectCornerBottomRight = 1 << 3,

UIRectCornerAllCorners  = ~0UL

};

/**

*  根据一个Rect 针对四角中的某个或多个角设置圆角

*

*  @param rect        CGRect一个矩形

*  @param corners     允许指定矩形的部分角为圆角,而其余的角为直角,取值来自枚举

*  @param cornerRadii  指定了圆角的半径,这个参数的取值是 CGSize 类型,也就意味着这里需要给出的是椭圆的半径。

*/

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

/**

*  以某个中心点画弧线

*  @param center     指定了圆弧所在正圆的圆心点坐标

*  @param radius     指定了圆弧所在正圆的半径

*  @param startAngle 指定了起始弧度位置  注意: 起始与结束这里是弧度

*  @param endAngle   指定了结束弧度位置

*  @param clockwise  指定了绘制方向,以时钟方向为判断基准   看下图

*/

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

图片来自网络

/**

*  根据CGPath创建并返回一个新的UIBezierPath对象

*  @param CGPath CGPathRef

*/

+ (instancetype)bezierPathWithCGPath:(CGPathRef)CGPath;

@property(nonatomic) CGPathRef CGPath;

- (CGPathRef)CGPath NS_RETURNS_INNER_POINTER CF_RETURNS_NOT_RETAINED;

/**

*  设置第一个起始点到接收器

*  @param point 起点坐标

*/

- (void)moveToPoint:(CGPoint)point;

/**

*  附加一条直线到接收器的路径

*  @param point 要到达的坐标

*/

- (void)addLineToPoint:(CGPoint)point;

/**

*  该方法就是画三次贝塞尔曲线的关键方法,以三个点画一段曲线,一般和moveToPoint:配合使用。其实端点为moveToPoint:设置,终止端点位为endPoint;。控制点1的坐标controlPoint1,这个参数可以调整。控制点2的坐标是controlPoint2。

*

*  @param endPoint      终点坐标

*  @param controlPoint1 控制点1

*  @param controlPoint2 控制点2  看下图

*/

- (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2;

图片来自网络

/**

*  画二次贝塞尔曲线,是通过调用此方法来实现的。一般和moveToPoint:配合使用。endPoint终端点,controlPoint控制点,对于二次贝塞尔曲线,只有一个控制点

*  @param endPoint     终点坐标

*  @param controlPoint 控制点  看下图

*/

- (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint;

图片来自网络

/**

*  添加一个弧线 与bezierPathWithArcCenter:radius:startAngle:endAngle:clockwise:区别是bezierPathWithArcCenter它是初始化一个弧线,addArcWithCenter是添加一个弧线,共同点就是参数都一样

*  @param center     指定了圆弧所在正圆的圆心点坐标

*  @param radius     指定了圆弧所在正圆的半径

*  @param startAngle 指定了起始弧度位置

*  @param endAngle   指定了结束弧度位置

*  @param clockwise  指定了绘制方向,以时钟方向为判断基准

*/

- (void)addArcWithCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise NS_AVAILABLE_IOS(4_0);

/**

*  闭合线 使用这个方法起始点与终点将相连

*/

- (void)closePath;

/**

*  移除所有坐标点

*/

- (void)removeAllPoints;

// Appending paths

// 添加一个paths UIBezierPath

- (void)appendPath:(UIBezierPath *)bezierPath;

// Modified paths

// 创建 并返回一个与当前路径相反的新的贝塞尔路径对象

- (UIBezierPath *)bezierPathByReversingPath NS_AVAILABLE_IOS(6_0);

// Transforming paths

// 用指定的仿射变换矩阵变换路径的所有点

- (void)applyTransform:(CGAffineTransform)transform;

// Path info

// 该值指示路径是否有任何有效的元素。

@property(readonly,getter=isEmpty) BOOL empty;

// 路径包括的矩形

@property(nonatomic,readonly) CGRect bounds;

// 图形路径中的当前点

@property(nonatomic,readonly) CGPoint currentPoint;

// 接收器是否包含指定的点

- (BOOL)containsPoint:(CGPoint)point;

// Drawing properties

// 线宽

@property(nonatomic) CGFloat lineWidth;

typedef CF_ENUM(int32_t, CGLineCap) {

kCGLineCapButt,  默认的

kCGLineCapRound, 轻微圆角

kCGLineCapSquare 正方形

};

// 端点类型

@property(nonatomic) CGLineCap lineCapStyle;

typedef CF_ENUM(int32_t, CGLineJoin) {

kCGLineJoinMiter, 默认的表示斜接

kCGLineJoinRound, 圆滑衔接

kCGLineJoinBevel  斜角连接

};

// 连接类型

@property(nonatomic) CGLineJoin lineJoinStyle;

// 最大斜接长度   斜接长度指的是在两条线交汇处内角和外角之间的距离

@property(nonatomic) CGFloat miterLimit; // Used when lineJoinStyle is kCGLineJoinMiter

/*

最大斜接长度   斜接长度指的是在两条线交汇处内角和外角之间的距离

只有lineJoin属性为kCALineJoinMiter时miterLimit才有效

边角的角度越小,斜接长度就会越大。

为了避免斜接长度过长,我们可以使用 miterLimit 属性。

如果斜接长度超过 miterLimit 的值,边角会以 lineJoin的 "bevel"即kCALineJoinBevel类型来显示

*/

// 确定弯曲路径短的绘制精度的因素

@property(nonatomic) CGFloat flatness;

// 一个bool值 指定even-odd规则是否在path可用

@property(nonatomic) BOOL usesEvenOddFillRule; // Default is NO. When YES, the even-odd fill rule is used for drawing, clipping, and hit testing.

// 设置线型

- (void)setLineDash:(nullable const CGFloat *)pattern count:(NSInteger)count phase:(CGFloat)phase;

//  检索线型

- (void)getLineDash:(nullable CGFloat *)pattern count:(nullable NSInteger *)count phase:(nullable CGFloat *)phase;

// Path operations on the current graphics context 当前图形上下文中的路径操作:

// 填充颜色

- (void)fill;

// 利用当前绘图属性沿着接收器的路径绘制

- (void)stroke;

// These methods do not affect the blend mode or alpha of the current graphics context

// 用指定的混合模式和透明度值来描绘受接收路径所包围的区域

- (void)fillWithBlendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha;

// 使用指定的混合模式和透明度值沿着接收器路径。绘制一行

- (void)strokeWithBlendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha;

// 剪切被接收者路径包围的区域 该路径是带有剪切路径的当前绘图上下文。使得其成为我们当前的剪切路径

- (void)addClip;

实践~敲出如下图代码

- (void)drawRect:(CGRect)rect {

UIColor *brushColor = [UIColor whiteColor];

// 根据一个Rect 画一个矩形曲线

UIBezierPath *rectangular = [UIBezierPath bezierPathWithRect:CGRectMake(5, 5, 30, 30)];

[PNRed set];

[rectangular fill];

[brushColor set];

[rectangular stroke];

// 根据一个Rect 画一个椭圆曲线  Rect为正方形时 画的是一个圆

UIBezierPath *oval = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(40, 5, 50, 30)];

[PNBlue set];

[oval fill];

[brushColor set];

[oval stroke];

// 根据一个Rect 画一个圆角矩形曲线 (Radius:圆角半径)    当Rect为正方形时且Radius等于边长一半时 画的是一个圆

UIBezierPath *roundedRect = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(95, 5, 40, 30) cornerRadius:5];

[PNStarYellow set];

[roundedRect fill];

[brushColor set];

[roundedRect stroke];

// 根据一个Rect 针对四角中的某个或多个角设置圆角

UIBezierPath *roundedRect2 = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(140, 5, 40, 30) byRoundingCorners:UIRectCornerTopLeft|UIRectCornerBottomRight cornerRadii:CGSizeMake(10, 50)];

[PNFreshGreen set];

[roundedRect2 fill];

[brushColor set];

[roundedRect2 stroke];

// 以某个中心点画弧线

UIBezierPath *arcPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(200, 15) radius:20 startAngle:0endAngle:degreesToRadian(90) clockwise:YES];

[brushColor set];

[arcPath stroke];

// 添加一个弧线

UIBezierPath *arcPath2 = [UIBezierPath bezierPath];

[arcPath2 moveToPoint:CGPointMake(230, 30)];

[arcPath2 addArcWithCenter:CGPointMake(265, 30) radius:25 startAngle:degreesToRadian(180)endAngle:degreesToRadian(360) clockwise:YES];

// 添加一个UIBezierPath

[arcPath2 appendPath:[UIBezierPath bezierPathWithArcCenter:CGPointMake(265, 30) radius:20 startAngle:0endAngle:M_PI*2 clockwise:YES]];

[PNStarYellow set];

[arcPath2 stroke];

// 根据CGPath创建并返回一个新的UIBezierPath对象

UIBezierPath *be = [self bezierPathWithCGPath];

[PNRed set];

[be stroke];

// 三角形

UIBezierPath *triangle = [UIBezierPath bezierPath];

[triangle moveToPoint:CGPointMake(145, 165)];

[triangle addLineToPoint:CGPointMake(155, 185)];

[triangle addLineToPoint:CGPointMake(135, 185)];

[PNStarYellow set];

[triangle fill];

//    [triangle stroke];

[triangle closePath];

// 二次贝塞尔曲线

UIBezierPath *quadBe = [UIBezierPath bezierPath];

[quadBe moveToPoint:CGPointMake(30, 150)];

[quadBe addQuadCurveToPoint:CGPointMake(130, 150) controlPoint:CGPointMake(30, 70)];

UIBezierPath *quadBe2 = [UIBezierPath bezierPath];

[quadBe2 moveToPoint:CGPointMake(160, 150)];

[quadBe2 addQuadCurveToPoint:CGPointMake(260, 150) controlPoint:CGPointMake(210, 50)];

[quadBe2 appendPath:quadBe];

quadBe2.lineWidth = 1.5f;

quadBe2.lineCapStyle = kCGLineCapSquare;

quadBe2.lineJoinStyle = kCGLineJoinRound;

[brushColor set];

[quadBe2 stroke];

// 三次贝塞尔曲线

UIBezierPath *threePath = [UIBezierPath bezierPath];

[threePath moveToPoint:CGPointMake(30, 250)];

[threePath addCurveToPoint:CGPointMake(260, 230) controlPoint1:CGPointMake(120, 180) controlPoint2:CGPointMake(150, 260)];

threePath.lineWidth = 1.5f;

threePath.lineCapStyle = kCGLineCapSquare;

threePath.lineJoinStyle = kCGLineJoinRound;

[brushColor set];

[threePath stroke];

}

- (UIBezierPath *)bezierPathWithCGPath {

UIBezierPath *framePath;

CGFloat arrowWidth = 14;

CGMutablePathRef path = CGPathCreateMutable();

CGRect rectangle = CGRectInset(CGRectMake(0, 0, CGRectGetWidth(self.bounds), CGRectGetWidth(self.bounds)), 3,3);

CGPoint p[3] = {

{CGRectGetMidX(self.bounds)-arrowWidth/2, CGRectGetWidth(self.bounds)-6},

{CGRectGetMidX(self.bounds)+arrowWidth/2, CGRectGetWidth(self.bounds)-6},

{CGRectGetMidX(self.bounds), CGRectGetHeight(self.bounds)-4}

};

CGPathAddRoundedRect(path, NULL, rectangle, 5, 5);

CGPathAddLines(path, NULL, p, 3);

CGPathCloseSubpath(path);

// 根据CGPath创建并返回一个新的UIBezierPath对象

framePath = [UIBezierPath bezierPathWithCGPath:path];

CGPathRelease(path);

return framePath;

}

下载源代码

 
 
 

UIBezierPath详解的更多相关文章

  1. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  2. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

  3. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

  4. Java 字符串格式化详解

    Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...

  5. Android Notification 详解(一)——基本操作

    Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...

  6. Android Notification 详解——基本操作

    Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...

  7. Git初探--笔记整理和Git命令详解

    几个重要的概念 首先先明确几个概念: WorkPlace : 工作区 Index: 暂存区 Repository: 本地仓库/版本库 Remote: 远程仓库 当在Remote(如Github)上面c ...

  8. Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)

    Android XML shape 标签使用详解   一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...

  9. Node.js npm 详解

    一.npm简介 安装npm请阅读我之前的文章Hello Node中npm安装那一部分,不过只介绍了linux平台,如果是其它平台,有前辈写了更加详细的介绍. npm的全称:Node Package M ...

随机推荐

  1. Java Socket编程 标准范例(多线程)

    链接地址:http://blog.csdn.net/benweizhu/article/details/6615542 服务器端(Server)非多线程 package com.zeph.server ...

  2. HOOK API(二)—— HOOK自己程序的 MessageBox

    HOOK API(二) —— HOOK自己程序的 MessageBox 0x00 前言 以下将给出一个简单的例子,作为HOOK API的入门.这里是HOOK 自己程序的MessageBox,即将自己程 ...

  3. UVa 11082 Matrix Decompressing(最大流)

    不想吐槽了..sample input 和sample output 完全对不上...调了一个晚上...不想说什么了... -------------------------------------- ...

  4. php 图片等比缩放

    /** * @method 图片等比缩放 * @param string $srcImage 源图片路径 * @param string $toFile 目标图片路径 * @param integer ...

  5. maven copy 依赖jar包

    <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-depen ...

  6. ThinkPHP第十五天(setField、setInc、setDec、关联模型)

    1.ThinkPHP中的比较特殊连贯操作 如果要更新某个字段可以用setField方法,比如M('user')->where('id=1')->setField('username','T ...

  7. mybatis CRUD

    方法一:通过配置文件 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBL ...

  8. ie7下div覆盖在iframe上方,ie8就不行,怎么解决

    <div style="position:relative;display:inline-block;width:178px;height:90px;z-index:9999;top: ...

  9. haproxy 超时机制

    <pre name="code" class="python">option redispatch option redispatch 是否允许重新 ...

  10. JAVA GUI学习 - 窗口【x】按钮关闭事件触发器:重写processWindowEvent(WindowEvent e)方法

    public class WindowListenerKnow extends JFrame { public WindowListenerKnow() { this.setBounds(300, 1 ...