记录寄己走过的路

iOS UIBezierPath译文

引导


记得刚接触 iOS 的时候, 第一次看到绘图和动画做出来的效果时,只有一个感觉酷!高大上!(默默下决心我要学会☺).
在写出这些牛X效果的前提 贝塞尔曲线这个东西我觉得要做到初步理解,然后梳理总结,到最后夯实基础、活学活用。



正题

在这里首先附上官方原文地址 UIBezierPath Class & UIBezierPath.h 属性和方法

Relationships
Inherits From NSObject 继承自: NSObject
Conforms To NSCoding, NSCopying 遵守: NSCoding,NSObject
Framework: UIKit in iOS 3_2 iOS 3.2+
Class
UIBezierPath

The UIBezierPath class lets you define a path consisting of straight and curved line segments and render that path in your custom views.
You use this class initially to specify just the geometry for your path.
Paths can define simple shapes such as rectangles, ovals, and arcs or they can define complex polygons that incorporate a mixture of straight and curved line segments.
After defining the shape, you can use additional methods of this class to render the path in the current drawing context.

UIBezierPath 类允许你在自定义的 View 中绘制和渲染由直线和曲线组成的路径. 你可以在初始化的时候, 直接为你的 UIBezierPath 指定一个几何路径. 路径可以是简单的几何图形例如: 矩形、椭圆、弧线之类的, 也可以是相对比较复杂的由直线和曲线组成的多边形. 当你定义完图形以后, 你可以使用这个类的其他的方法将你的路径直接绘制在当前的绘图上下文中.

Overview

A UIBezierPath object combines the geometry of a path with attributes that describe the path during rendering. You set the geometry and attributes separately and can change them independent of one another. Once you have the object configured the way you want it, you can tell it to draw itself in the current context. Because the creation, configuration, and rendering process are all distinct steps, Bezier path objects can be reused easily in your code. You can even use the same object to render the same shape multiple times, perhaps changing the rendering options between successive drawing calls.

UIBezierPath 是由几何路径 和 属性描述组成的, 属性是用来在渲染阶段描绘几何路径的, 比如线宽之类的东西. 路径和属性是完全独立的, 他们并不互相依赖, 你可以分开分开去设置他们. 一旦你以自己喜欢的方式配置了 UIBezierPath 对象, 你就可以调用方法通知UIBezierPath 在当前的绘图上下文中绘制图形了. 因为创建、 配置、 渲染路径等操作, 都是完全不同的步骤, 所以你可以在你的代码中非常容易的对UIBezierPath 对象进行复用. 你甚至可以使用同一个 UIBezierPath 对象去渲染同一个图形很多次, 你也可以再多次渲染的间隔中, 修改属性来渲染出不同样式的路径.

You set the geometry of a path by manipulating the path’s current point. When you create a new empty path object, the current point is undefined and must be set explicitly. To move the current point without drawing a segment, you use the moveToPoint:method. All other methods result in the addition of either a line or curve segments to the path. The methods for adding new segments always assume you are starting at the current point and ending at some new point that you specify. After adding the segment, the end point of the new segment automatically becomes the current point.

你可以通过控制路径的当前的(起始)点来设置一条路径的形状,当你创建了一个空的UIBezierPath 对象时, 起始点currentPoint 这个属性是未定义的, 你需要手动的去设置.currentPoint. 如果你希望在不绘制任何线条的情况下移动currentPoint, 你可以使用 moveToPoint:方法. 其他的方法都会导致在你的路径中添加额外的直线或曲线. 所有构造路径相关的方法, 都会以当前路径的currentPoint 为起点, 以你指定的endPoint为终点进行绘制. 当完成绘制之后, 会自动将新增的这条线的终点设置为UIBezierPath 对象的currentPoint.

A single Bezier path object can contain any number of open or closed subpaths, where each subpath represents a connected series of path segments. Calling the closePath method closes a subpath by adding a straight line segment from the current point to the first point in the subpath. Calling the moveToPoint: method ends the current subpath (without closing it) and sets the starting point of the next subpath. The subpaths of a Bezier path object share the same drawing attributes and must be manipulated as a group. To draw subpaths with different attributes, you must put each subpath in its own UIBezierPath object.

一个单一的贝塞尔路径对象能够包含任意数量的开放和闭合的子路径,在这些路径的线段中,每一个线段都是串联的. 调用closePath方法将会闭合路径, 它将会从currentPoint 到 子路经的 firstPoint起点绘制一条直线. 调用moveToPoint:方法将会结束当前的子路径, 但是并不会自动闭合当前的自路径, 并且会将currentPoint 移动到指定的点, 也就是下一条绘制路径的起始点.UIBezierPath中所有的自路径都会共享同样的绘图属性. 如果你希望绘制一些子路径, 但是不适用相同的绘图属性, 那么你就只能创建很多的UIBezierPath 对象来承载每一条路径.

After configuring the geometry and attributes of a Bezier path, you draw the path in the current graphics context using the stroke and fill methods. The stroke method traces the outline of the path using the current stroke color and the attributes of the Bezier path object. Similarly, the fill method fills in the area enclosed by the path using the current fill color. (You set the stroke and fill color using the UIColor class.)

当你为UIBezierPath 对象配置完几何路径和绘图属性之后, 你就可以使用stroke描边(空心) 和 fill填充(实心) 方法在当前的绘图上下文中进行绘制了. stroke方法将会使用当前的strokeColor 和 绘图属性来描绘曲线的轮廓. 同样的, fill 方法将会使用fillColor 来填充路径所围成的图形(使用UIColor 类方法来设置strokeColorfillColor).

In addition to using a Bezier path object to draw shapes, you can also use it to define a new clipping region. The addClip method intersects the shape represented by the path object with the current clipping region of the graphics context. During subsequent drawing, only content that lies within the new intersection region is actually rendered to the graphics context.

除了可以用贝塞尔路径对象去绘制图形,你还可以利用它去定义个新的裁剪区域.addClip方法通过当前图形上下文裁剪的区域的路径对象来表示两个图形的相交. 在随后的绘制过程中,只有处在新的交集区域内的内容实际上是被图形上下文绘制的

然后我们就直接从UIBezierPath.h 入手吧

UIBezierPath.h


创建 UIBezierPath
1
2
// Objective-C
+ (instancetype)bezierPath;
1
2
3
4
5
6
7
8
9
/**
* 画矩形
* 该方法将会创建一个闭合路径, 起始点是 rect 参数的的 origin, 并且按照顺时针方向添加直线, 最终形成矩形
* @param rect: 矩形路径的 Frame
*/
// Swift
convenience init(rect rect: CGRect)
// Objective-C
+ (instancetype)bezierPathWithRect:(CGRect)rect;
1
2
3
4
5
6
7
8
9
/**
* 画圆(width = height)、画椭圆(width != height)
* 该方法将会创建一个闭合路径, 该方法会通过顺时针的绘制贝塞尔曲线, 绘制出一个近似椭圆的形状. 如果 rect 参数指定了一个矩形, 那么该 UIBezierPath 对象将会描述一个圆形.
* @param rect: 矩形路径的 Frame
*/
// Swift
convenience init(ovalInRect rect: CGRect)
// Objective-C
+ (instancetype)bezierPathWithOvalInRect:(CGRect)rect;
1
2
3
4
5
6
7
8
9
10
11
/**
* 画圆角矩形
* 该方法将会创建一个闭合路径, 该方法会顺时针方向连续绘制直线和曲线. 当 rect 为正方形时且 cornerRadius 等于边长一半时, 则该方法会描述一个圆形路径.
* @param rect: 矩形路径的 Frame
* @param cornerRadius: 矩形的圆角半径
*/
// Swift
convenience init(roundedRect rect: CGRect,
cornerRadius cornerRadius: CGFloat)
// Objective-C
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius; // rounds all corners with the same horizontal and vertical radius
1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 画指定角为圆角的矩形
* 该方法将会创建一个闭合路径, 该方法会顺时针方向连续绘制直线和曲线.
* @param rect: 矩形路径的 Frame
* @param corners: UIRectCorner 枚举类型, 指定矩形的哪个角变为圆角
* @param cornerRadii: 矩形的圆角半径
*/
// Swift
convenience init(roundedRect rect: CGRect,
byRoundingCorners corners: UIRectCorner,
cornerRadii cornerRadii: CGSize)
// Objective-C
+ (instancetype)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 画圆弧
* 该方法会创建出一个开放路径, 创建出来的圆弧是圆的一部分. 在默认的坐标系统中, 开始角度 和 结束角度 都是基于单位圆的(看下面这张图). 调用这个方法之后, currentPoint 将会设置为圆弧的结束点.
* @param center: 弧所在的圆心(这里不能直接用self.center,因为它是相对于它的父控件的,采用rect 宽度*0.5、高度*0.5)
* @param radius: 圆的半径
* @param startAngle: 开始角度
* @param endAngle: 结束角度
* @param clockwise: 是否顺时针绘制(YES顺时针 NO逆时针)
*/
// Swift
convenience init(arcCenter center: CGPoint,
radius radius: CGFloat,
startAngle startAngle: CGFloat,
endAngle endAngle: CGFloat,
clockwise clockwise: Bool)
// Objective-C
+ (instancetype)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;

图片摘自苹果官网.jpg

1
2
3
4
// Swift
convenience init(CGPath CGPath: CGPath)
// Objective-C
+ (instancetype)bezierPathWithCGPath:(CGPathRef)CGPath;
1
2
3
4
5
6
7
8
9
// Modified paths
/**
* 通过该方法反转一条路径, 并不会修改该路径的样子. 它仅仅是修改了绘制的方向
* @return: 返回一个新的 UIBezierPath 对象, 形状和原来路径的形状一样,但是绘制的方向相反.
*/
// Swift
func bezierPathByReversingPath() -> UIBezierPath
// Objective-C
- (UIBezierPath *)bezierPathByReversingPath NS_AVAILABLE_IOS(6_0);
构造路径
1
2
3
4
5
6
7
8
9
10
// Path construction
/**
* 设置起点
* 如果当前有正在绘制的子路径, 该方法则会隐式的结束当前路径, 并将 currentPoint 设置为指定点.
* @param point: 当前坐标系统中的某一点
*/
// Swift
func moveToPoint(_ point: CGPoint)
// Objective-C
- (void)moveToPoint:(CGPoint)point;
1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 添加一根线到终点
* 该方法将会从 currentPoint 到 指定点 链接一条直线.
* @param point: 绘制直线的终点坐标, 当前坐标系统中的某一点
* Note: 在追加完这条直线后, 该方法将会更新 currentPoint 为 指定点
调用该方法之前, 你必须先设置 currentPoint. 如果当前绘制路径
为空, 并且未设置 currentPoint, 那么调用该方法将不会产生任何
效果.
*/
// Swift
func addLineToPoint(_ point: CGPoint)
// Objective-C
- (void)addLineToPoint:(CGPoint)point;
1
2
3
4
5
6
7
8
9
10
11
/**
* 画指定一条圆弧
* 该方法将会从 currentPoint 添加一条指定的圆弧.
* 该方法的介绍和 bezierPathWithArcCenter构造方法中的一样. 请前往上文查看
* @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);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 画二次贝塞尔曲线(由一个控制点来控制)
* 该方法将会从 currentPoint 到 指定的 endPoint 追加一条二次贝塞尔曲线.
* currentPoint、endPoint、controlPoint 三者的关系最终定义了二次贝塞尔曲线的形状.
* 二次贝塞尔曲线的弯曲由一个控制点来控制. 如下图所示
Note: 调用该方法前, 你必须先设置 currentPoint, 如果路径为空,
并且尚未设置 currentPoint, 调用该方法则不会产生任何效果.
当添加完贝塞尔曲线后, 该方法将会自动更新 currentPoint 为
指定的结束点
* @param endPoint: 终点
* @param controlPoint: 弯曲方向点1
*/
// Swift
func addQuadCurveToPoint(_ endPoint: CGPoint,
controlPoint controlPoint: CGPoint)
// Objective-C
- (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint;

二次贝塞尔曲线.jpg

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 画三次贝塞尔曲线(由两个控制点来控制)
* 该方法将会从 currentPoint 到 指定的 endPoint 追加一条三次贝塞尔曲线.
* 三次贝塞尔曲线的弯曲由两个控制点来控制. 如下图所示
* Note: 调用该方法前, 你必须先设置 currentPoint, 如果路径为空,
并且尚未设置 currentPoint, 调用该方法则不会产生任何效果.
当添加完贝塞尔曲线后, 该方法将会自动更新 currentPoint 为
指定的结束点
* @param endPoint: 终点
* @param controlPoint1: 弯曲方向点1
* @param controlPoint2: 弯曲方向点2
*/
// Swift
func addCurveToPoint(_ endPoint: CGPoint,
controlPoint1 controlPoint1: CGPoint,
controlPoint2 controlPoint2: CGPoint)
// Objective-C
- (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2;

三次贝塞尔曲线.jpg

1
2
3
4
5
6
7
8
9
10
/**
* 闭合路径
* 该方法将会从 currentPoint 到子路经的起点 绘制一条直线,
* 以此来关闭当前的自路径. 紧接着该方法将会更新 currentPoint
* 为 刚添加的这条直线的终点, 也就是当前子路经的起点.
*/
// Swift
func closePath()
// Objective-C
- (void)closePath;
1
2
3
4
// Swift
func removeAllPoints()
// Objective-C
- (void)removeAllPoints;
1
2
3
4
5
6
7
8
9
/**
* 追加路径
* 该方法将会在当前 UIBezierPath 对象的路径中追加
* 指定的 UIBezierPath 对象中的内容.
*/
// Swift
func appendPath(_ bezierPath: UIBezierPath)
// Objective-C
- (void)appendPath:(UIBezierPath *)bezierPath;
1
2
3
4
5
6
7
8
9
10
11
/**
* 获取这个属性, 你将会获得一个不可变的 CGPathRef 对象,
* 他可以传入 CoreGraphics 提供的函数中
* 你可以是用 CoreGraphics 框架提供的方法创建一个路径,
* 并给这个属性赋值, 当时设置了一个新的路径后,
* 这个将会对你给出的路径对象进行 Copy 操作
*/
// Swift
var CGPath: CGPath
// Objective-C
@property(nonatomic) CGPathRef CGPath;
1
2
3
4
5
6
7
8
/**
* 该属性的值, 将会是下一条绘制的直线或曲线的起始点.
* 如果当前路径为空, 那么该属性的值将会是 CGPointZero
*/
// Swift
var currentPoint: CGPoint { get }
// Objective-C
@property(nonatomic, readonly) CGPoint currentPoint;
绘图属性
1
2
3
4
5
6
7
/**
* 线宽属性定义了 `UIBezierPath` 对象中绘制的曲线规格. 默认为: 1.0
*/
// Swift
var lineWidth: CGFloat
// Objective-C
@property(nonatomic) CGFloat lineWidth;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 该属性应用于曲线的终点和起点. 该属性在一个闭合子路经中是无效果的. 默认为: kCGLineCapButt
*/
// Swift
var lineCapStyle: CGLineCap
// Objective-C
@property(nonatomic) CGLineCap lineCapStyle;
/* Line cap styles. */
typedef CF_ENUM(int32_t, CGLineCap) {
kCGLineCapButt,//
kCGLineCapRound,// 圆弧
kCGLineCapSquare //
};

曲线终点样式.jpeg

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 默认为: kCGLineJoinMiter.
*/
// Swift
var lineJoinStyle: CGLineJoin
// Objective-C
@property(nonatomic) CGLineJoin lineJoinStyle;
/* Line join styles. */
typedef CF_ENUM(int32_t, CGLineJoin) {
kCGLineJoinMiter,// 尖的
kCGLineJoinRound,// 圆弧
kCGLineJoinBevel // 斜面
};

曲线连接点样.jpeg

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 斜接点长度
* 两条线交汇处内角和外角之间的最大距离, 只有当连接点样式为 kCGLineJoinMiter
* 时才会生效,最大限制为10
* 我们都知道, 两条直线相交时, 夹角越小, 斜接长度就越大.
* 该属性就是用来控制最大斜接长度的.
* 当我们设置了该属性, 如果斜接长度超过我们设置的范围,
* 则连接处将会以 kCGLineJoinBevel 连接类型进行显示.
*/
// Swift
var miterLimit: CGFloat
// Objective-C
@property(nonatomic) CGFloat miterLimit;

斜接点长度.jpeg

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 该属性用来确定渲染曲线路径的精确度.
* 该属性的值用来测量真实曲线的点和渲染曲线的点的最大允许距离.
* 值越小, 渲染精度越高, 会产生相对更平滑的曲线, 但是需要花费更
* 多的计算时间. 值越大导致则会降低渲染精度, 这会使得渲染的更迅速. flatness 的默认值为 0.6.
* Note: 大多数情况下, 我们都不需要修改这个属性的值. 然而当我们
希望以最小的消耗去绘制一个临时的曲线时, 我们也许会临时增
大这个值, 来获得更快的渲染速度.
*/
// Swift
var flatness: CGFloat
// Objective-C
@property(nonatomic) CGFloat flatness;
1
2
3
4
5
6
7
8
/**
* 设置为 YES, 则路径将会使用 基偶规则 (even-odd) 进行填充.
* 设置为 NO, 则路径将会使用 非零规则 (non-zero) 规则进行填充.
*/
// Swift
var usesEvenOddFillRule: Bool
// Objective-C
@property(nonatomic) BOOL usesEvenOddFillRule;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* @param pattern: 该属性是一个 C 语言的数组, 其中每一个元素都是 CGFloat
数组中的元素代表着线段每一部分的长度, 第一个元素代表线段的第一条线,
第二个元素代表线段中的第一个间隙. 这个数组中的值是轮流的. 来解释一下
什么叫轮流的.
* 举个例子: 声明一个数组 CGFloat dash[] = @{3.0, 1.0};
这意味着绘制的虚线的第一部分长度为3.0, 第一个间隙长度为1.0, 虚线的
第二部分长度为3.0, 第二个间隙长度为1.0. 以此类推.
* @param count: 这个参数是 pattern 数组的个数
* @param phase: 这个参数代表着, 虚线从哪里开始绘制.
* 举个例子: 这是 phase 为 6. pattern[] = @{5, 2, 3, 2}; 那么虚线将会
第一个间隙的中间部分开始绘制, 如果不是很明白就请继续往下看,
下文实战部分会对虚线进行讲解.
*/
// Swift
func setLineDash(_ pattern: UnsafePointer<CGFloat>,
count count: Int,
phase phase: CGFloat)
// Objective-C
- (void)setLineDash:(const CGFloat *)pattern
count:(NSInteger)count
phase:(CGFloat)phase;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 该方法可以重新获取之前设置过的虚线样式.
* Note: pattern 这个参数的容量必须大于该方法返回数组的容量.
如果无法确定数组的容量, 那么可以调用两次该方法, 第一次
调用该方法的时候, 传入 count 参数, 然后在用 count 参数
来申请 pattern 数组的内存空间. 然后再第二次正常的调用该方法
*/
// Swift
func getLineDash(_ pattern: UnsafeMutablePointer<CGFloat>,
count count: UnsafeMutablePointer<Int>,
phase phase: UnsafeMutablePointer<CGFloat>)
// Objective-C
- (void)getLineDash:(CGFloat *)pattern
count:(NSInteger *)count
phase:(CGFloat *)phase;
绘制路径
1
2
3
4
5
6
7
8
9
10
11
/**
* 填充(实心)
* 该方法当前的填充颜色 和 绘图属性对路径的封闭区域进行填充.
* 如果当前路径是一条开放路径, 该方法将会隐式的将路径进行关闭后进行填充
* 该方法在进行填充操作之前, 会自动保存当前绘图的状态, 所以我们不需要
* 自己手动的去保存绘图状态了.
*/
// Swift
func fill()
// Objective-C
- (void)fill;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 该方法当前的填充颜色 和 绘图属性 (外加指定的混合模式 和 透明度)
* 对路径的封闭区域进行填充. 如果当前路径是一条开放路径, 该方法将
* 会隐式的将路径进行关闭后进行填充
* 该方法在进行填充操作之前, 会自动保存当前绘图的状态, 所以我们不需要
* 自己手动的去保存绘图状态了.
*
* @param blendMode: 混合模式决定了如何和已经存在的被渲染过的内容进行合成
* @param alpha: 填充路径时的透明度
*/
// Swift
func fillWithBlendMode(_ blendMode: CGBlendMode,
alpha alpha: CGFloat)
// Objective-C
- (void)fillWithBlendMode:(CGBlendMode)blendMode
alpha:(CGFloat)alpha;
1
2
3
4
// Swift
func stroke()
// Objective-C
- (void)stroke;
1
2
3
4
5
6
7
8
9
/**
* @param blendMode: 混合模式决定了如何和已经存在的被渲染过的内容进行合成
* @param alpha: 填充路径时的透明度
*/
// Swift
func strokeWithBlendMode(_ blendMode: CGBlendMode,alpha alpha: CGFloat)
// Objective-C
- (void)strokeWithBlendMode:(CGBlendMode)blendMode
alpha:(CGFloat)alpha;
剪切路径
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 该方法将会修改当前绘图上下文的可视区域.
* 当调用这个方法之后, 会导致接下来所有的渲染操作,
只会在剪切下来的区域内进行, 区域外的内容将不会被渲染.
* 如果你希望执行接下来的绘图时, 删除剪切区域,
那么你必须在调用该方法前, 先使用CGContextSaveGState 方法保存当前的绘图状态,
当你不再需要这个剪切区域的时候, 你只需要使用 CGContextRestoreGState 方法,
来恢复之前保存的绘图状态就可以了.
* @param blendMode: 混合模式决定了如何和已经存在的被渲染过的内容进行合成
* @param alpha: 填充路径时的透明度
*/
// Swift
func addClip()
// Objective-C
- (void)addClip;
Hit Detection
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 该方法返回一个布尔值, 当曲线的覆盖区域包含
* 指定的点(内部点), 则返回 YES, 否则返回 NO.
* Note: 如果当前的路径是一个开放的路径, 那么
就算指定点在路径覆盖范围内, 该方法仍然会
返回 NO, 所以如果你想判断一个点是否在一个
开放路径的范围内时, 你需要先Copy一份路径,
并调用 -(void)closePath; 将路径封闭, 然后
再调用此方法来判断指定点是否是内部点.
* @param point: 指定点.
*/
// Swift
func containsPoint(_ point: CGPoint) -> Bool
// Objective-C
- (BOOL) containsPoint:(CGPoint)point;
1
2
3
4
5
6
7
8
9
/**
* 检测当前路径是否绘制过直线或曲线.
* Note: 记住, 就算你仅仅调用了 moveToPoint 方法
那么当前路径也被看做不为空.
*/
// Swift
var empty: Bool { get }
// Objective-C
@property (readonly, getter=isEmpty) BOOL empty;
1
2
3
4
5
6
7
8
9
/**
* 该属性描述的是一个能够完全包含路径中所有点
* 的一个最小的矩形区域. 该区域包含二次贝塞尔
* 曲线和三次贝塞尔曲线的控制点.
*/
// Swift
var bounds: CGRect { get }
// Objective-C
@property (nonatomic, readonly) CGRect bounds;
1
2
3
4
5
6
7
8
/**
* 该方法将会直接对路径中的所有点进行指定的放射
* 变换操作.
*/
// Swift
func applyTransform(_ transform: CGAffineTransform)
// Objective-C
- (void)applyTransform:(CGAffineTransform)transform;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// Swift
struct UIRectCorner : OptionSetType {
init(rawValue rawValue: UInt)
static var TopLeft: UIRectCorner { get }
static var TopRight: UIRectCorner { get }
static var BottomLeft: UIRectCorner { get }
static var BottomRight: UIRectCorner { get }
static var AllCorners: UIRectCorner { get }
}
// Objective-C
enum {
UIRectCornerTopLeft = 1 << 0,
UIRectCornerTopRight = 1 << 1,
UIRectCornerBottomLeft = 1 << 2,
UIRectCornerBottomRight = 1 << 3,
UIRectCornerAllCorners = ~0
};
typedef NSUInteger UIRectCorner;
常数(Constants):
UIRectCornerTopLeft
The top-left corner of the rectangle.
矩形的左上角.
Available in iOS 3.2 and later.
UIRectCornerTopRight
The top-right corner of the rectangle.
矩形的右上角.
Available in iOS 3.2 and later.
UIRectCornerBottomLeft
The bottom-left corner of the rectangle.
矩形的左下角.
Available in iOS 3.2 and later.
UIRectCornerBottomRight
The bottom-right corner of the rectangle.
矩形的右下角.
Available in iOS 3.2 and later.
UIRectCornerAllCorners
All corners of the rectangle.
矩形的所有的角.
Available in iOS 3.2 and later.
指定的常数反映了一个没有被 仿射变换修改和已经在默认坐标系上绘制的矩形的所有角.(原点在左上角和 ??扩散的值(positive values)向下延伸到右边).
导入声明(Import Statement)
// Swift
import UIKit
// Objective-C
@import UIKit;
实战示例

UIBezierPath.h 文件大家完全的过了一遍了, 其实看上去还是蛮简单过的昂.. 接下来就到了激动人心的实战环节了. 我们来简单的写几句代码, 看看效果吧.
1、bezierPathByReversingPath:路径反转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
- (void) drawRect:(CGRect)rect {
// 1. 随便画一个路径出来.
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint: CGPointMake(10, 10)];
[path addLineToPoint: CGPointMake(80, 40)];
[path addLineToPoint: CGPointMake( 40, 80)];
[path addLineToPoint: CGPointMake(40, 40)];
path.lineWidth = 3;
// 2. 为这条路径制作一个反转路径
UIBezierPath *reversingPath = [path bezierPathByReversingPath];
reversingPath.lineWidth = 3;
// 3. 为了避免两条路径混淆在一起, 我们为第一条路径做一个位移
CGAffineTransform transform = CGAffineTransformMakeTranslation(200, 0);
[path applyTransform: transform];
// 4. 设置颜色, 并绘制路径
[[UIColor redColor] set];
[path stroke];
[[UIColor greenColor] set];
[reversingPath stroke];
}

效果:
路径反转.png

2、setLineDash: 虚线

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
- (void) typeDashLine {
// 1. 先创建三条路径, 有对比更有助于理解
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint: CGPointMake(80, 40)];
[path addLineToPoint: CGPointMake(self.frame.size.width - 40, 40)];
path.lineWidth = 2;
UIBezierPath *path1 = [UIBezierPath bezierPath];
[path1 moveToPoint: CGPointMake(80, 80)];
[path1 addLineToPoint: CGPointMake(self.frame.size.width - 40, 80)];
path1.lineWidth = 2;
UIBezierPath *path2 = [UIBezierPath bezierPath];
[path2 moveToPoint: CGPointMake(80, 120)];
[path2 addLineToPoint: CGPointMake(self.frame.size.width - 40, 120)];
path2.lineWidth = 2;
// 2. 这部分是配置三条路径虚线的规格, 重点主要是这部分.
CGFloat dashLineConfig[] = {8.0, 4.0};
[path setLineDash: dashLineConfig count: 2 phase: 0];
CGFloat dashLineConfig1[] = {8.0, 4.0, 16.0, 8.0};
[path1 setLineDash: dashLineConfig1 count: 4 phase: 0];
CGFloat dashLineConfig2[] = {8.0, 4.0, 16.0, 8.0};
[path2 setLineDash: dashLineConfig2 count: 4 phase: 12];
// 3. 绘制
[[UIColor orangeColor] set];
[path stroke];
[path1 stroke];
[path2 stroke];
}

效果:
虚线.jpeg

要想做出多牛逼酷炫的动画效果,就必须承受同等学习的代价 !

期待


  • 如果在阅读过程中遇到 error || new ideas,希望你能 messages 我,我会及时改正谢谢。

  • 点击右上角的 喜欢 和 订阅Rss 按钮,可以收藏本仓库,并在 Demo 更新时收到邮件通知。

❄︎ 本文结束    感谢简阅 ^_^. ❄︎

本文标题:iOS UIBezierPath译文

文章作者:寄己的路

原始链接:https://sunyonghui.github.io/AppleTranslation/UIBezierPathApple.html

版权声明: 署名-非商业性使用-禁止演绎 4.0 国际 本博客所有文章除特别声明外均为原创,转载务必请「注明出处链接(可点击) - 作者」,并通过E-mail等方式告知,谢谢合作!