CodeV

4.12-弯曲的形状

图4-14显示了通过围绕中心点添加三次曲线而构建的简单形状的示例。它是通过使用构建您在图4-15中看到的形状的相同的方法创建的。

图4-15-1
图4-15-2

图4-15弯曲变化:这里显示的第四和第五形状使用了穿过中心的大的反向弯曲拐点。顶行:8点和-0.5弯曲,12点和-0.75弯曲,8点和0.5弯曲。底行:8点和-2.5弯曲,12点和-2.5弯曲,12点和2.5弯曲。

如果你认为代码4-9中的代码看起来和代码4-8中的多边形生成器非常相似,你说得对。两个函数之间的区别是,代码清单4-9在它的点之间创建了一条曲线,而不是绘制一条直线。您可以指定要创建的曲线数量。

该曲线的拐点由两个控制点建立。这些点由您传递给函数的percentInflection参数设置。正弯曲拐点离中心越远,围绕形状建立的越像波瓣(lobes)。负弯曲拐点折向中心移动,甚至穿过中心,从而产生您在其他图上看到的尖峰和环。

清单4-9 Generating Inflected Shapes

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
UIBezierPath *BezierInflectedShape(
NSUInteger numberOfInflections,
CGFloat percentInflection)
{
if (numberOfInflections < 3)
{
NSLog(@"Error: Please supply at least 3 inflections");
return nil;
}

UIBezierPath *path = [UIBezierPath bezierPath];
CGRect destinationRect = CGRectMake(0, 0, 1, 1);
CGPoint center = RectGetCenter(destinationRect);
CGFloat r = 0.5;
CGFloat rr = r * (1.0 + percentInflection);

BOOL firstPoint = YES;
for (int i = 0; i < numberOfInflections; i++)
{
CGFloat theta = i * TWO_PI / numberOfInflections;
CGFloat dTheta = TWO_PI / numberOfInflections;

if (firstPoint)
{
CGFloat xa = center.x + r * sin(theta);
CGFloat ya = center.y + r * cos(theta);
CGPoint pa = CGPointMake(xa, ya);
[path moveToPoint:pa];
firstPoint = NO;
}

CGFloat cp1x = center.x + rr * sin(theta + dTheta / 3);
CGFloat cp1y = center.y + rr * cos(theta + dTheta / 3);
CGPoint cp1 = CGPointMake(cp1x, cp1y);

CGFloat cp2x = center.x + rr * sin(theta + 2 * dTheta / 3);
CGFloat cp2y = center.y + rr * cos(theta + 2 * dTheta / 3);
CGPoint cp2 = CGPointMake(cp2x, cp2y);

CGFloat xb = center.x + r * sin(theta + dTheta);
CGFloat yb = center.y + r * cos(theta + dTheta);
CGPoint pb = CGPointMake(xb, yb);

[path addCurveToPoint:pb controlPoint1:cp1 controlPoint2:cp2];
}

[path closePath];
return path;
}

通过调整代码清单4-9来绘制线而不是曲线,您可以创建星形形状。在代码清单4-10中,位于每个点之间中间的单个控制点提供了星形的角度的目的地。图4-16重点介绍了使用代码清单4-10生成的一些形状。

图4-16-1
图4-16-2

图4-16用清单4-10构建的各种星星。顶行:5点和0.75拐点,8点和0.5拐点,9点和-2拐点。底行:6点和-1.5拐点,12点和0.75拐点(并填充)。最后一个项目使用偶数/奇数填充规则,使用BezierStarShape(12,-2.5)构建。

清单4-10Generating Star Shapes

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
UIBezierPath *BezierStarShape(
NSUInteger numberOfInflections, CGFloat percentInflection)
{
if (numberOfInflections < 3)
{
NSLog(@"Error: Please supply at least 3 inflections");
return nil;
}

UIBezierPath *path = [UIBezierPath bezierPath];
CGRect destinationRect = CGRectMake(0, 0, 1, 1);
CGPoint center = RectGetCenter(destinationRect);
CGFloat r = 0.5;
CGFloat rr = r * (1.0 + percentInflection);

BOOL firstPoint = YES;
for (int i = 0; i < numberOfInflections; i++)
{
CGFloat theta = i * TWO_PI / numberOfInflections;
CGFloat dTheta = TWO_PI / numberOfInflections;

if (firstPoint)
{
CGFloat xa = center.x + r * sin(theta);
CGFloat ya = center.y + r * cos(theta);
CGPoint pa = CGPointMake(xa, ya);
[path moveToPoint:pa];
firstPoint = NO;
}

CGFloat cp1x = center.x + rr * sin(theta + dTheta / 2);
CGFloat cp1y = center.y + rr * cos(theta + dTheta / 2);
CGPoint cp1 = CGPointMake(cp1x, cp1y);

CGFloat xb = center.x + r * sin(theta + dTheta);
CGFloat yb = center.y + r * cos(theta + dTheta);
CGPoint pb = CGPointMake(xb, yb);

[path addLineToPoint:cp1];
[path addLineToPoint:pb];
}

[path closePath];
return path;
}

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