英文:
UIBezierPath roundedRect has strange gaps
问题
I need to draw a rounded rect. However, at very special corner radius values (between 34 to 37), it causes very strange bugs like the image below. Can someone explain to me why it happened?
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)
}
}
英文:
I need to draw a rounded rect. However, at very special corner radius values (between 34 to 37), it causes very strange bugs like the image below. Can someone explain to me why it happened?
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)
}
}
答案1
得分: 2
I suspect that a rounded rectangle is implemented by joining some curves together and the artifact that you are seeing is caused by the lineJoin
property of the layer.
Setting lineJoin
to .round
fixes it for me:
layer.lineJoin = .round
英文:
I suspect that a rounded rectangle is implemented by joining some curves together and the artifact that you are seeing is caused by the lineJoin
property of the layer.
Setting lineJoin
to .round
fixes it for me:
layer.lineJoin = .round
答案2
得分: 0
使用2个贝塞尔路径并填充颜色,而不是使用单个路径描边。
问题是CALayer使用多个路径创建边框,导致路径重叠,然后与填充规则evenOdd混合,导致奇怪的行为。这也使得创建完美圆形变得不可能。
这篇文章解释了为什么会发生这种情况。
感谢Zalo iOS VietNam团队帮助我理解这个问题。
我的解决方案是通过使用2个分开的路径并在它们之间填充颜色来避免重叠。
另一种修复方法是使用CGMutablePath。
func draw() {
let rect = CGRect(x: 30, y: 50, width: 200, height: 100)
let borderWidth: CGFloat = 5
let cornerRadius: CGFloat = 5
let outerPath = UIBezierPath(roundedRect: rect, byRoundingCorners: .allCorners, cornerRadii: CGSize(width: cornerRadius, height: cornerRadius))
let innerRect = CGRect(x: rect.minX + borderWidth, y: rect.minY + borderWidth, width: rect.width - borderWidth * 2, height: rect.height - borderWidth * 2)
let innerPath = UIBezierPath(roundedRect: innerRect, byRoundingCorners: .allCorners, cornerRadii: CGSize(width: cornerRadius, height: cornerRadius))
let path = UIBezierPath()
path.append(outerPath)
path.append(innerPath)
let layer = CAShapeLayer()
layer.fillColor = UIColor.red.cgColor
layer.fillRule = .evenOdd
layer.path = path.cgPath
self.view.layer.addSublayer(layer)
}
英文:
Using 2 bezierpath and fill with color instead of using single path with stroke.
The problem is CALayer using multiple path to create a border, cause overlap between the path then it mixed with fill rule .evenOdd cause weird behavior.
This also make impossible to create a perfect circle.
This article explained why is it happened.
https://www.paintcodeapp.com/blogpost/code-for-ios-7-rounded-rectangles
Thanks Zalo iOS VietNam team to help me understand this.
My solution to avoid overlap by using 2 separated paths and fill color between them.
The another way to fix is using 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)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论