To create a squircle shape (a combination of a square and a circle, also known as a superellipse) in SwiftUI, you can define a custom shape by conforming to the Shape
protocol and implementing the superellipse formula. The formula for a superellipse is:
[ \left(\frac{x}{a}\right)^{n} + \left(\frac{y}{b}\right)^{n} = 1 ]
Where:
a
andb
are the semi-major and semi-minor axes (which are equal for a squircle, making it symmetrical).n
is the exponent that determines the curvature (typically around 4 for a squircle).
Implementing a Squircle Shape in SwiftUI
Here’s how to define a squircle shape:
import SwiftUI
struct SquircleShape: Shape {
var curvature: CGFloat = 4
func path(in rect: CGRect) -> Path {
let a = rect.width / 2
let b = rect.height / 2
var path = Path()
path.move(to: CGPoint(x: rect.midX + a, y: rect.midY))
for angle in stride(from: 0.0, to: 360.0, by: 1.0) {
let radians = angle * .pi / 180
let x = pow(abs(cos(radians)), 2 / curvature) * a * sign(cos(radians))
let y = pow(abs(sin(radians)), 2 / curvature) * b * sign(sin(radians))
path.addLine(to: CGPoint(x: rect.midX + x, y: rect.midY + y))
}
path.closeSubpath()
return path
}
private func sign(_ value: CGFloat) -> CGFloat {
return value >= 0 ? 1 : -1
}
}
Explanation
path(in rect: CGRect)
: This function defines the shape of the squircle within a given rectangle (rect
).- Superellipse Formula: The
x
andy
coordinates are calculated using the superellipse formula, wheren
controls the roundness. For example,n = 2
would give you an ellipse, whilen = 4
gives the squircle shape. sign(_:)
: This helper function is used to maintain the correct sign forx
andy
values when calculating the points on the squircle.
Using the Squircle Shape
You can use the SquircleShape
just like any other SwiftUI shape:
struct ContentView: View {
var body: some View {
SquircleShape()
.fill(Color.blue)
.frame(width: 200, height: 200)
.padding()
}
}
Customizing the Squircle
You can adjust the n
value in the SquircleShape
struct to change the curvature:
- n < 4: The shape becomes more circular.
- n > 4: The shape becomes more square-like, but with rounded corners.
Now you can adjust the curvature when using the shape:
SquircleShape(curvature: 4)
.fill(Color.blue)
.frame(width: 200, height: 200)
Yes, you can adjust the value of n
in the superellipse formula to create a range of shapes, from a full circle to a square or rectangle with rounded corners. Here’s how it works:
Superellipse Formula Recap
The formula for a superellipse is:
[ \left(\frac{x}{a}\right)^{n} + \left(\frac{y}{b}\right)^{n} = 1 ]
Where:
a
andb
are the semi-major and semi-minor axes.n
controls the curvature:- n = 2: Perfect circle (when
a = b
). - n > 2: As
n
increases, the shape becomes more square-like with rounded corners. - n < 2: As
n
decreases, the shape becomes more diamond-like (but this isn’t typically used for the squircle or standard rounded rectangles).
- n = 2: Perfect circle (when
Adjusting n
for Different Shapes
- Full Circle (
n = 2
):- When
n = 2
, the shape is a perfect circle ifa = b
. Ifa
andb
are different, it will be an ellipse.
- When
- Rounded Rectangle / Squircle (
n = 4
):- When
n = 4
, you get a typical squircle or a rounded rectangle shape. The corners are more rounded compared ton > 4
.
- When
- More Square-Like with Rounded Corners (
n > 4
):- As
n
increases beyond 4, the shape becomes more like a square or rectangle with less pronounced rounding of the corners.
- As
Usage Examples:
- Circle (
n = 2
):CustomShape(curvature: 2) .fill(Color.blue) .frame(width: 200, height: 200)
This will give you a perfect circle.
- Squircle (
n = 4
):CustomShape(curvature: 4) .fill(Color.red) .frame(width: 200, height: 200)
This will give you the standard squircle shape.
- Rounded Rectangle with Less Curvature (
n > 4
):CustomShape(curvature: 8) .fill(Color.green) .frame(width: 200, height: 200)
This will give you a shape closer to a square with slightly rounded corners.
Example with Different Shapes in a View:
struct ContentView: View {
var body: some View {
VStack {
CustomShape(curvature: 2)
.fill(Color.blue)
.frame(width: 200, height: 200)
.padding()
CustomShape(curvature: 4)
.fill(Color.red)
.frame(width: 200, height: 200)
.padding()
CustomShape(curvature: 8)
.fill(Color.green)
.frame(width: 200, height: 200)
.padding()
}
}
}
Conclusion
By defining a custom Shape
and using the superellipse formula, you can create a squircle shape in SwiftUI that closely matches the shape used in Apple’s app icons. This shape can be used in various UI elements, providing a smooth and modern appearance.
And, by adjusting the value of n
, you can seamlessly transition between different shapes, from a full circle to a square or rectangle with varying degrees of rounded corners. This flexibility allows you to create a wide range of custom shapes in SwiftUI that can be tailored to your specific design needs.