Created
January 4, 2022 11:32
-
-
Save Tmw/c9f25d34ef9f4b5997f76dec40f0cc34 to your computer and use it in GitHub Desktop.
RoundedRectangle with per-corner radii
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
// | |
// RoundableRectangle.swift | |
// Created by Tiemen Waterreus on 20/12/2021. | |
// | |
import SwiftUI | |
/// RoundableRectangle is a shape (rounded rectangle) where each | |
/// corner of the rectangle can be rounded with a separate radius | |
struct RoundableRectangle: Shape { | |
// By defining animatableData as AnimatablePair we can animate pairs of properties of the shape. | |
// since we'er keeping track of all four corners separately, we'd need two pairs to store the four separate value. | |
var animatableData: AnimatablePair<AnimatablePair<CGFloat, CGFloat>, AnimatablePair<CGFloat, CGFloat>> { | |
get { AnimatablePair(AnimatablePair(topLeftRadius, topRightRadius), AnimatablePair(bottomLeftRadius, bottomRightRadius)) } | |
set { | |
topLeftRadius = newValue.first.first | |
topRightRadius = newValue.first.second | |
bottomLeftRadius = newValue.second.first | |
bottomRightRadius = newValue.second.second | |
} | |
} | |
var topLeftRadius: CGFloat = 22 | |
var topRightRadius: CGFloat = 22 | |
var bottomRightRadius: CGFloat = 16 | |
var bottomLeftRadius: CGFloat = 16 | |
func path(in rect: CGRect) -> Path { | |
var path = Path() | |
// line from top left corner to top right corner | |
path.move(to: CGPoint(x: rect.minX + topLeftRadius, y: rect.minY)) | |
path.addLine(to: CGPoint(x: rect.maxX - topRightRadius, y: rect.minY)) | |
// top right corner | |
path.addArc( | |
center: CGPoint(x: rect.maxX - topRightRadius, y: rect.minY + topRightRadius), | |
radius: topRightRadius, | |
startAngle: Angle(degrees: -90), | |
endAngle: Angle(degrees: 0), | |
clockwise: false | |
) | |
// right side line | |
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY - bottomRightRadius)) | |
// bottom right corner | |
path.addArc( | |
center: CGPoint(x: rect.maxX - bottomRightRadius, y: rect.maxY - bottomRightRadius), | |
radius: bottomRightRadius, | |
startAngle: Angle(degrees: 0), | |
endAngle: Angle(degrees: 90), | |
clockwise: false | |
) | |
// bottom line | |
path.addLine(to: CGPoint(x: rect.minX + bottomLeftRadius, y: rect.maxY)) | |
// bottom left corner | |
path.addArc( | |
center: CGPoint(x: rect.minX + bottomLeftRadius, y: rect.maxY - bottomLeftRadius), | |
radius: bottomLeftRadius, | |
startAngle: Angle(degrees: 90), | |
endAngle: Angle(degrees: -180), | |
clockwise: false | |
) | |
// left side line | |
path.addLine(to: CGPoint(x: rect.minX, y: rect.minY + topLeftRadius)) | |
// top left corner | |
path.addArc( | |
center: CGPoint(x: rect.minX + topLeftRadius, y: rect.minY + topLeftRadius), | |
radius: topLeftRadius, | |
startAngle: Angle(degrees: -180), | |
endAngle: Angle(degrees: -90), | |
clockwise: false | |
) | |
return Path(path.cgPath) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment