Last active
October 25, 2023 14:14
-
-
Save renssies/96ab3ba1426ad97fa91497b59a4d73c3 to your computer and use it in GitHub Desktop.
Rounded UIBezierPath without clamping bug
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extension UIBezierPath { | |
/// Creates a rounded rectangle without clamping the corner radius the 1/3 of the rects width or height. | |
/// This can be used to workout a bug in the standard `UIBezierPath(roundedRect:cornerRadius)`. | |
/// | |
/// It will however clamp the corner radius to a max of half the width or height of the rect, this is to avoid incorrect drawing. | |
/// - Parameters: | |
/// - rect: The rectangle that defines the basic shape of the path | |
/// - cornerRadius: The radius of each corner oval. A value of 0 results in a rectangle without rounded corners. Values larger than half the rectangle’s width or height are clamped appropriately to half the width or height. | |
convenience init(unclampedRoundedRect rect: CGRect, cornerRadius: CGFloat) { | |
self.init() | |
let cornerRadius = min(cornerRadius, rect.width / 2, rect.height / 2) | |
let path = self | |
path.move(to: CGPoint(x: 0 + cornerRadius, y: 0)); // Move to top left but inset with radius | |
path.addLine(to: CGPoint(x: rect.width - cornerRadius, y: 0)) // Add line at the top from left to right | |
path.addArc(withCenter: CGPoint(x: rect.width - cornerRadius, y: cornerRadius), radius: cornerRadius, startAngle: 3 * .pi / 2, endAngle: 0, clockwise: true) // Add top right rounded corner | |
path.addLine(to: CGPoint(x: rect.width, y: rect.height - cornerRadius)) // Add line from top to bottom on right side | |
path.addArc(withCenter: CGPoint(x: rect.width - cornerRadius, y: rect.height - cornerRadius), radius: cornerRadius, startAngle: 0, endAngle: .pi / 2, clockwise: true) // Add bottom right rounded corner | |
path.addLine(to: CGPoint(x: cornerRadius, y: rect.height)) // Add line from bottom right to bottom left | |
path.addArc(withCenter: CGPoint(x: cornerRadius, y: rect.height - cornerRadius), radius: cornerRadius, startAngle: .pi / 2, endAngle: .pi, clockwise: true) // Add bottom left rounded corner | |
path.addLine(to: CGPoint(x: 0, y: cornerRadius)) // Add line from bottom to top on left side | |
path.addArc(withCenter: CGPoint(x: cornerRadius, y: cornerRadius), radius: cornerRadius, startAngle: .pi, endAngle: 3 * .pi / 2, clockwise: true) // Add top left rounded corner | |
path.close() // Complete the path | |
} | |
} |
You're not considering the X and Y origins, I made some changes.
`let cornerRadius = min(cornerRadius, rect.width / 2, rect.height / 2)
let originX = rect.origin.x
let originY = rect.origin.y
let width = rect.size.width
let height = rect.size.height
let path = self
path.move(to: CGPoint(x: originX + cornerRadius, y: originY)) // Move to top left but inset with radius
path.addLine(to: CGPoint(x: originX + width - cornerRadius, y: originY)) // Add line at the top from left to right
path.addArc(withCenter: CGPoint(x: originX + width - cornerRadius, y: originY + cornerRadius),
radius: cornerRadius, startAngle: 3 * .pi / 2, endAngle: 0,
clockwise: true) // Add top right rounded corner
path.addLine(to: CGPoint(x: originX + width, y: originY + height - cornerRadius)) // Add line from top to bottom on right side
path.addArc(withCenter: CGPoint(x: originX + width - cornerRadius, y: originY + height - cornerRadius),
radius: cornerRadius, startAngle: 0, endAngle: .pi / 2,
clockwise: true) // Add bottom right rounded corner
path.addLine(to: CGPoint(x: originX + cornerRadius, y: originY + height)) // Add line from bottom right to bottom left
path.addArc(withCenter: CGPoint(x: originX + cornerRadius, y: originY + height - cornerRadius),
radius: cornerRadius, startAngle: .pi / 2, endAngle: .pi,
clockwise: true) // Add bottom left rounded corner
path.addLine(to: CGPoint(x: originX, y: originY + cornerRadius)) // Add line from bottom to top on left side
path.addArc(withCenter: CGPoint(x: originX + cornerRadius, y: originY + cornerRadius),
radius: cornerRadius, startAngle: .pi, endAngle: 3 * .pi / 2,
clockwise: true) // Add top left rounded corner
path.close() // Complete the path`
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@kirill-chuyanov I've fixed it, looks like I've already fixed it in my own code, but didn't update this gist, thanks for the reminder :)