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 macos September 3, 2024 Two ways to open a window programmatically in SwiftUI

SwiftUI provides an openWindow environment variable on macOS that allows you to open windows programmatically. Here’s how you can use it to open a new window when a button is clicked:

question swiftui swift October 7, 2024 How to zoom in and zoom out a SwiftUI view?

In a macOS or iOS app, you can easily add a zoom feature to any SwiftUI view with the scaleEffect modifier. In the below example, I am using a Slider to control the zoom level. Here’s how you can implement zooming in and out with a slider:

question swiftui swift September 7, 2024 How to apply mirroring to any SwiftUI view?

You can apply mirroring to a SwiftUI view by using the scaleEffect(x:y:anchor:) modifier to flip the view horizontally or vertically. Specifically, you can set the x or y scale to -1.0 to mirror the view along that axis.