我设计了这个代码来生成一个Bezier路径,用作CAShapeLayer掩盖UIView的路径(视图的高度和宽度是可变的)
这段代码生成一个边缘锐利的三角形,但我想让它成为一个圆角!我花了2个小时尝试使用 addArcWithCenter...
, lineCapStyle
和 lineJoinStyle
等,但似乎没有什么对我有用 .
UIBezierPath *bezierPath = [UIBezierPath bezierPath];
CGPoint center = CGPointMake(rect.size.width / 2, 0);
CGPoint bottomLeft = CGPointMake(10, rect.size.height - 0);
CGPoint bottomRight = CGPointMake(rect.size.width - 0, rect.size.height - 0);
[bezierPath moveToPoint:center];
[bezierPath addLineToPoint:bottomLeft];
[bezierPath addLineToPoint:bottomRight];
[bezierPath closePath];
所以我的问题是,如何在UIBezierPath中舍入三角形的所有边缘(我需要子层,多路径等)吗?
N.B我不是在绘制这个BezierPath所以 drawRect
中的所有 CGContext...
函数都无法帮助我:(
谢谢!
6 回答
更复杂的是,只需添加两行代码:
EDIT:
要看到角是圆角的,你需要使三角形比直线边界小一点:
基于@ David的answer我写了一个小的
UIBezierPath
扩展,它添加了与CGPath相同的功能:所以有了这个,代码应该是这样的:
编辑
FWIW: 这个答案通过解释
CGPathAddArcToPoint(...)
为您做什么来达到其教育目的 . 我强烈建议您仔细阅读,因为它将帮助您理解和欣赏CGPath API . 那么你应该继续使用它,如an0's answer中所示,而不是在您的应用程序中舍入边缘时使用此代码 . 如果您想要使用此代码并且了解这样的几何计算,则此代码应仅用作参考 .原始答案
因为我发现这样的问题很有趣,我不得不回答:)
这是一个很长的答案 . 没有简短的版本:D
注意:为了我自己的简单,我的解决方案是对用于形成三角形的点做出一些假设,例如:
三角形的面积足够大以适合圆角(例如,三角形的高度大于角落中圆圈的直径 . 我没有检查或试图阻止任何可能的奇怪结果否则发生 .
角以逆时针顺序列出 . 您可以使它适用于任何订单,但为了简单起见,它感觉像是一个公平的约束 .
如果你愿意,你可以使用相同的技术来对任何多边形进行舍入,只要它尽可能地解释如何做,但它遵循相同的原则 .
这一切都以一个三角形开始,你想要用一些半径圆角,r:
圆角三角形应该包含在尖三角形中,所以第一步是找到尽可能靠近角落的位置,在这里您可以使用半径r来拟合圆 .
这样做的一种简单方法是在三角形中创建3条平行于3条边的新线,并将每条距离r向内移动,与原始边的侧面正交 .
为此,您需要计算每条线的斜率/角度以及要应用于两个新点的偏移量:
注意:为了清楚起见,我使用的是CGVector类型(在iOS 7中可用),但您也可以使用点或大小来使用以前的OS版本 .
然后将偏移量添加到每行的起点和终点:
当你这样做时,你会看到三条线在三个地方相互交叉:
每个交叉点恰好是两个边的距离r(假设三角形足够大,如上所述) .
您可以将两条线的交点计算为:
其中(x1,y1)到(x2,y2)是第一行,(x3,y3)到(x4,y4)是第二行 .
如果然后在每个交点上放置一个半径为r的圆,则可以看到它确实是圆角三角形(忽略三角形和圆形的不同线宽):
现在要创建一个圆角三角形,您要创建一条路径,该路径从一条线变为一条弧,再变换为原始三角形与交叉点正交的点上的线(等) . 这也是圆与原始三角形相切的点 .
知道三角形中所有3个边的斜率,圆角半径和圆的中心(交点),每个圆角的起始和终止角度是该边的斜率--90度 . 为了将这些东西组合在一起,我在我的代码中创建了一个结构,但如果你不想这样做,则不必:
为了减少代码重复,我为自己创建了一个方法,计算一个点的交点和角度给定从一个点到另一个点的线到最终点(它没有关闭,所以它不是三角形):
代码如下(它实际上只是我上面显示的代码,放在一起):
然后,我使用该代码3次来计算3角落:
现在,拥有所有必要的数据,启动我们创建实际路径的部分 . 我将依赖于CGPathAddArc将从当前点添加到起点的直线而不必自己绘制这些行(这是记录的行为) .
我手动必须计算的唯一点是路径的起点 . 我选择右下角的开头(没有具体原因) . 从那里你只需添加一个圆弧,中心位于从起点和终点角度的交点:
看起来像这样:
没有所有支持线的最终结果如下所示:
@ David的几何学很酷且很有教育意义 . 但是你真的不需要以这种方式完成整个几何体 . 我将提供一个更简单的代码:
bezierPath
是你需要的 . 关键是CGPathAddArcToPoint
为你做几何 .Swift 4中的圆角三角形
基于@ an0的answer以上:
将三角形创建为UIBezierPath
@ an0-谢谢!我是全新的,所以我没有声称有用或评论的声誉,但你今天节省了我很多时间 .
我知道这超出了问题的范围,但是相同的逻辑适用于
CGContextBeginPath()
,CGContextMoveToPoint()
,CGContextAddArcToPoint()
和CGContextClosePath()
,以防任何人需要使用它 .如果有人有兴趣,这是我的等边三角形指向右边的代码 .
triangleFrame
是预定义的CGRect
,radius
是预定义的CGFloat
.当然,可以针对不规则三角形更具体地定义每个点 . 您可以根据需要
CGContextFillPath()
或CGContextStrokePath()
.