如果这个形状是纯色,简单的解决方案是使用非常宽的线宽,加上圆线帽和圆线连接。不过,我假设您希望这个圆形完全位于您包含在图片中的形状内。然后诀窍是将您绘制的弧线偏移等于路径角半径的量(并以角半径宽度的两倍画线)。
例如,考虑这个图表(它不是我们想要的形状,但告诉我们如何到达那里):
背景中的黑色形状是您的原始形状。白色路径是我要绘制的实现圆角的路径。浅灰色是用大线宽、圆形线连接和圆形线帽描边的路径。深灰色是用另一种颜色填充的路径。
所以希望这能说明这个想法。创建一条新路径,偏移圆角半径,并以两倍于圆角半径的线宽绘制。如果您只是简单地使用实心的背面描边(替换上图中的浅灰色)和纯黑色填充(替换上图中的深灰色)绘制新路径,您将获得所需的形状:
这是在 Objective-C 中获取路径(我的第一张图片中的白线)的例程:
- (UIBezierPath *)arcWithRoundedCornerAt:(CGPoint)center
startAngle:(CGFloat)startAngle
endAngle:(CGFloat)endAngle
innerRadius:(CGFloat)innerRadius
outerRadius:(CGFloat)outerRadius
cornerRadius:(CGFloat)cornerRadius {
CGFloat innerTheta = asin(cornerRadius / 2.0 / (innerRadius + cornerRadius)) * 2.0;
CGFloat outerTheta = asin(cornerRadius / 2.0 / (outerRadius - cornerRadius)) * 2.0;
UIBezierPath *path = [UIBezierPath bezierPath];
[path addArcWithCenter:center
radius:innerRadius + cornerRadius
startAngle:endAngle - innerTheta
endAngle:startAngle + innerTheta
clockwise:false];
[path addArcWithCenter:center
radius:outerRadius - cornerRadius
startAngle:startAngle + outerTheta
endAngle:endAngle - outerTheta
clockwise:true];
[path closePath];
return path;
}
或者在 Swift 3 中:
private func arcWithRoundedCorners(at center: CGPoint, startAngle: CGFloat, endAngle: CGFloat, innerRadius: CGFloat, outerRadius: CGFloat, cornerRadius: CGFloat) -> UIBezierPath {
let innerTheta = asin(cornerRadius / 2 / (innerRadius + cornerRadius)) * 2
let outerTheta = asin(cornerRadius / 2 / (outerRadius - cornerRadius)) * 2
let path = UIBezierPath()
path.addArc(withCenter: center, radius: innerRadius + cornerRadius, startAngle: endAngle - innerTheta, endAngle: startAngle + innerTheta, clockwise: false)
path.addArc(withCenter: center, radius: outerRadius - cornerRadius, startAngle: startAngle + outerTheta, endAngle: endAngle - outerTheta, clockwise: true)
path.close()
return path
}
(如果需要,您可以使用 Core Graphics 调用执行上述操作,但我通常使用 UIBezierPath。)
但是,如果您需要填充与描边不同的颜色,那么过程会更加复杂,因为您不能只使用这种技术。相反,您实际上必须定义一条路径,它是上述形状的轮廓,但不仅包括绘制两条大弧线,还包括为每个角绘制四个小弧线。构建这条路径很乏味,但很简单,三角函数,但除非你必须这样做,否则我不会这样做。