Skip to content

Instantly share code, notes, and snippets.

@Tmw
Created January 4, 2022 11:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Tmw/c9f25d34ef9f4b5997f76dec40f0cc34 to your computer and use it in GitHub Desktop.
Save Tmw/c9f25d34ef9f4b5997f76dec40f0cc34 to your computer and use it in GitHub Desktop.
RoundedRectangle with per-corner radii
//
// 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