UIBezierPath roundedRect 有奇怪的间隙

问题描述 投票:0回答:2

我需要画一个圆角矩形。然而,在非常特殊的角半径值(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)
        
    }
}


ios swift uikit core-graphics
2个回答
2
投票

我怀疑圆角矩形是通过将一些曲线连接在一起实现的,而您看到的伪像是由图层的

lineJoin
属性引起的。

设置

lineJoin
.round
为我修复它:

layer.lineJoin = .round


0
投票

使用 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)
    }
© www.soinside.com 2019 - 2024. All rights reserved.