CodeV

5.1-路径元素

您可以在图5-1中看到,UIBezierPath类支持三种贝塞尔元素:线段,二次曲线和三次曲线。每个元素代表描述路径布局方式的五个操作之一:

  • kCGPathElementMoveToPoint - 此元素将路径的位置设置为新位置,但不添加任何直线或曲线。
  • kCGPathElementAddLineToPoint - 此元素将从上一点到(当前)元素的位置添加线段。如您会在图5-1中顶部图看到的线段。
  • kCGPathElementAddQuadCurveToPoint - 此元素添加从前一点到(当前)元素位置的二次曲线。图5-1中的中间图使用单个控制点构建为二次曲线。
  • kCGPathElementAddCurveToPoint - 此元素将从上一个点添加一个三次曲线到元素的位置。图5-1中的底部图显示了一个三次曲线,其中有两个控制点。
  • kCGPathElementCloseSubpath - 此元素关闭子路径,从当前点绘制一条线到最近的子路径的开始位置。此开始位置始终使用“move to point”元素设置。

图5-1

图5-1您可以从直线(顶部图),具有单个控制点的二次曲线(中间图)和具有两个控制点的三次曲线(下部图)构造贝塞尔路径。

每个CGPathElement存储一个元素类型(你刚刚看到的五种类型之一)和一个CGPoint项目数组:

1
2
3
4
struct CGPathElement {
CGPathElementType type;
CGPoint *points;
};

元素的points数组可以存储零个,一个,两个或三个点。数量取决于元素在路径中的角色。关闭路径元素不定义任何点。move-to-point和line-to-point元素使用一个,它们指定了目的地(包括开始点)。目的地告诉元素移动到哪里或在哪里添加一条直线。

除了目的地之外,二次和三次曲线都需要控制点。二线曲线存储目的地和一个控制点。三次曲线存储目的地和两个控制点。此外,这些点的顺序因点类型而异。

在Objective-C类中包含这些路径元素,如清单5-1所示,简化了它们的使用。此类隐藏点数组的复杂性及其实现细节,例如哪个项目是目标点,哪些项目是控制点。每个基于元素的对象表示一组一致的属性,成为许多方便的UIBezierPath实用程序的垫脚石。

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
55
56
57
58
59
#define NULLPOINT CGRectNull.origin

@interface BezierElement : NSObject <NSCopying>
@property (nonatomic, assign) CGPathElementType elementType;
@property (nonatomic, assign) CGPoint point;
@property (nonatomic, assign) CGPoint controlPoint1;
@property (nonatomic, assign) CGPoint controlPoint2;
@end

@implementation BezierElement
- (instancetype) init
{
self = [super init];
if (self)
{
_elementType = kCGPathElementMoveToPoint;
_point = NULLPOINT;
_controlPoint1 = NULLPOINT;
_controlPoint2 = NULLPOINT;
}
return self;
}

// Create a BezierElement object that represents
// the data stored in the passed element
+ (instancetype) elementWithPathElement:(CGPathElement) element
{
BezierElement *newElement = [[self alloc] init];
newElement.elementType = element.type;

switch (newElement.elementType)
{
case kCGPathElementCloseSubpath:
break;
case kCGPathElementMoveToPoint:
case kCGPathElementAddLineToPoint:
{
newElement.point = element.points[0];
break;
}
case kCGPathElementAddQuadCurveToPoint:
{
newElement.point = element.points[1];
newElement.controlPoint1 = element.points[0];
break;
}
case kCGPathElementAddCurveToPoint:
{
newElement.point = element.points[2];
newElement.controlPoint1 = element.points[0];
newElement.controlPoint2 = element.points[1];
break;
}
default:
break;
}

return newElement;
}

本文翻译自《iOS Drawing Practical UIKit Solutions》作者:Erica Sadun,翻译:Cheng Dong。如果觉得本书不错请购买支持正版:亚马逊购买传送门,本书所有源代码可在GitHub上下载。译者虽然力求做到信,达,雅,但是由于时间仓促加之译者水平十分有限,文中难免会出现不正确,不准确,词不达意,难于理解的地方,还望各位批评指正,共同进步,谢谢。转载请注明出处。