Created
July 6, 2020 16:15
-
-
Save renssies/5c430a2790d7dc63f396f6a51e03d1fa to your computer and use it in GitHub Desktop.
Create a rounded UIBezierPath with a different corner radius per corner
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 { | |
/// Defines a corner of a rounded rectangle path. | |
public enum RoundedRectCorner { | |
case topLeft | |
case topRight | |
case bottomLeft | |
case bottomRight | |
case all | |
} | |
/// Creates a rounded rectangle with the given corners. | |
/// This allows the creation of a rectangle with a different corner radius for one of more corners. | |
/// | |
/// Be warned that this method does not clamp the corner radius for specific corners. It is possible to end up with an invalid or incorrect path while doing this. | |
/// | |
/// **Example** | |
/// | |
/// In order to change 1 corner from the rest, simply supply `.all` and the corner you want to change to `corners:`. | |
/// `[.all: 26, .bottomRight: 9]` | |
/// | |
/// - Parameters: | |
/// - rect: The rectangle that defines the basic shape of the path | |
/// - corners: The corners to adjust the corner radius for. The specific corner will always take priority over the `all` option. | |
convenience init(roundedRect rect: CGRect, corners: [RoundedRectCorner: CGFloat]) { | |
self.init() | |
let allCorners = min(corners[.all] ?? 0, rect.width / 2, rect.height / 2) | |
let topLeft = corners[.topLeft] ?? allCorners | |
let topRight = corners[.topRight] ?? allCorners | |
let bottomLeft = corners[.bottomLeft] ?? allCorners | |
let bottomRight = corners[.bottomRight] ?? allCorners | |
let path = self | |
path.move(to: CGPoint(x: 0 + topLeft, y: 0)); // Move to top left but inset with radius | |
path.addLine(to: CGPoint(x: rect.width - topRight, y: 0)) // Add line at the top from left to right | |
path.addArc(withCenter: CGPoint(x: rect.width - topRight, y: topRight), radius: topRight, startAngle: 3 * .pi / 2, endAngle: 0, clockwise: true) // Add top right rounded corner | |
path.addLine(to: CGPoint(x: rect.width, y: rect.height - bottomRight)) // Add line from top to bottom on right side | |
path.addArc(withCenter: CGPoint(x: rect.height - bottomRight, y: rect.width - bottomRight), radius: bottomRight, startAngle: 0, endAngle: .pi / 2, clockwise: true) // Add bottom right rounded corner | |
path.addLine(to: CGPoint(x: bottomLeft, y: rect.height)) // Add line from bottom right to bottom left | |
path.addArc(withCenter: CGPoint(x: bottomLeft, y: rect.height - bottomLeft), radius: bottomLeft, startAngle: .pi / 2, endAngle: .pi, clockwise: true) // Add bottom left rounded corner | |
path.addLine(to: CGPoint(x: 0, y: topLeft)) // Add line from bottom to top on left side | |
path.addArc(withCenter: CGPoint(x: topLeft, y: topLeft), radius: topLeft, 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