Loading...

How to make Squircle shape in SwiftUI and how to easily convert it to a circle or a rectangle?

question swiftui swift
Ram Patra Published on September 8, 2024

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 and b 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 and y coordinates are calculated using the superellipse formula, where n controls the roundness. For example, n = 2 would give you an ellipse, while n = 4 gives the squircle shape.
  • sign(_:): This helper function is used to maintain the correct sign for x and y 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 and b 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).

Adjusting n for Different Shapes

  1. Full Circle (n = 2):
    • When n = 2, the shape is a perfect circle if a = b. If a and b are different, it will be an ellipse.
  2. Rounded Rectangle / Squircle (n = 4):
    • When n = 4, you get a typical squircle or a rounded rectangle shape. The corners are more rounded compared to n > 4.
  3. 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.

Usage Examples:

  1. Circle (n = 2):
    CustomShape(curvature: 2)
        .fill(Color.blue)
        .frame(width: 200, height: 200)
    

    This will give you a perfect circle.

  2. Squircle (n = 4):
    CustomShape(curvature: 4)
        .fill(Color.red)
        .frame(width: 200, height: 200)
    

    This will give you the standard squircle shape.

  3. 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.

Presentify

Take your presentation to the next level.

FaceScreen

Put your face and name on your screen.

ToDoBar

Your to-dos on your menu bar.

Ram Patra Published on September 8, 2024
Image placeholder

Keep reading

If this article was helpful, others might be too

question swiftui swift August 31, 2024 @StateObject vs @ObservedObject in SwiftUI

In SwiftUI, both @StateObject and @ObservedObject are property wrappers used to manage state in your views, specifically when working with objects that conform to the ObservableObject protocol. However, they serve slightly different purposes and have different use cases. Here’s a breakdown:

question swiftui swift September 13, 2024 How to add a character limit to a TextField in SwiftUI?

To add a character length limit to a TextField in SwiftUI, you can use a combination of Swift’s .onChange, .onPasteCommand modifier, and string manipulation to limit the number of characters the user can enter.

question swiftui iOS April 2, 2024 How to open a second view from first view in iOS using SwiftUI?

In SwiftUI, you can open another view (or navigate to another view) on the click of a button by utilizing navigation views and navigation links. Here’s a basic example of how to achieve this: