我需要画一个圆角矩形。然而,在非常特殊的角半径值(34 到 37 之间)下,它会导致非常奇怪的错误,如下图所示。有人可以向我解释为什么会这样吗?
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
drawView()
self.view.backgroundColor = .red
}
func drawView() {
let rect = CGRect(x: 100, y: 100, width: 200, height: 100)
let borderWidth = 10.0
let cornerRadius = 34.0
let layer = CAShapeLayer()
layer.strokeColor = UIColor.green.cgColor
layer.lineWidth = borderWidth
layer.fillColor = UIColor.white.cgColor
let path = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius)
layer.path = path.cgPath
self.view.layer.addSublayer(layer)
}
}
使用 2 个 bezierpath 并用颜色填充,而不是使用带有笔划的单个路径。
问题是 CALayer 使用多个路径创建边框,导致路径之间重叠然后它与填充规则混合。evenOdd 导致奇怪的行为。 这也使得不可能创建一个完美的圆圈。
这篇文章解释了为什么会这样。
https://www.paintcodeapp.com/blogpost/code-for-ios-7-rounded-rectangles
感谢 Zalo iOS VietNam 团队帮助我理解这一点。
我的解决方案是通过使用 2 个单独的路径并在它们之间填充颜色来避免重叠。
另一种修复方法是使用 CGMutablePath。
func draw() {
let rect = CGRect(x: 30, y: 50, width: 200, height: 100)
let boderWidth: CGFloat = 5
let cornerRadius: CGFloat = 5
let outterPath = UIBezierPath(roundedRect: rect, byRoundingCorners: .allCorners, cornerRadii: CGSize(width: cornerRadius, height: cornerRadius))
let innerRect = CGRect(x: rect.minX + boderWidth, y: rect.minY + boderWidth, width: rect.width - boderWidth * 2, height: rect.height - boderWidth * 2)
let innerPath = UIBezierPath(roundedRect: innerRect, byRoundingCorners: .allCorners, cornerRadii: CGSize(width: cornerRadius, height: cornerRadius))
let path = UIBezierPath()
path.append(outterPath)
path.append(innerPath)
let layer = CAShapeLayer()
layer.fillColor = UIColor.red.cgColor
layer.fillRule = .evenOdd
layer.path = path.cgPath
self.view.layer.addSublayer(layer)
}