skip to Main Content

I’m working on creating a "bridge" shape in SwiftUI by combining a rectangle and a circle. I believe using a method like .union might be the solution, but I’m having trouble figuring out how to implement it correctly. My goal is to merge a rectangle and a circle to create a shape that resembles a bridge. Specifically, I want the top side of the rectangle to have an inset curve. Additionally, I’d like to place an image in the background of this composite shape. Essentially, the final design should be a rectangle with a curved inset at the top and an image set behind it.

Some help woud be great! thanks

ZStack {
        Rectangle()
            .fill(.blue)
            .frame(height:250)

       Image("BGImage")
        
        Circle()
            .fill(.white)
            .frame(width: 700)
            .offset(y:-400)
    }

Thats the goal:

Screenshot

2

Answers


  1.     import SwiftUI
    
    struct BridgeShape: Shape {
        func path(in rect: CGRect) -> Path {
            let width = rect.width
            let height = rect.height
        
        let bridgeHeight: CGFloat = height * 0.7 // Adjust the height of the bridge
        let curveHeight: CGFloat = height * 0.1 // Adjust the height of the curved inset
        
        var path = Path()
        
        // Starting from the top-left corner
        path.move(to: CGPoint(x: 0, y: 0))
        
        // Top horizontal line
        path.addLine(to: CGPoint(x: width, y: 0))
        
        // Top right curve inset
        path.addQuadCurve(to: CGPoint(x: width, y: curveHeight), control: CGPoint(x: width * 0.8, y: curveHeight))
        
        // Top right corner of the bridge
        path.addLine(to: CGPoint(x: width, y: bridgeHeight))
        
        // Bottom right corner
        path.addLine(to: CGPoint(x: 0, y: bridgeHeight))
        
        // Closing the shape
        path.closeSubpath()
        
        return path
    }
    }
    
    struct ContentView: View {
        var body: some View {
            ZStack {
                Image("BGImage")
                    .resizable()
                    .scaledToFill()
                    .edgesIgnoringSafeArea(.all)
            
            BridgeShape()
                .fill(Color.blue)
                .frame(height: 250)
        }
    }
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
        }
    

    Replace "BGImage" with the name of your image asset. Adjust the values of bridgeHeight and curveHeight in the BridgeShape struct to modify the appearance of the bridge as needed.

    Login or Signup to reply.
  2. When you say you want to:

    place an image in the background of this composite shape

    do you mean, the image should be behind the shape (in other words, the shape covers parts of the image), or do you want the shape to be filled with the image?

    • If you want the image to be behind the shape then a Shape is probably the best approach, because then the image will then show through the non-filled area(s) of the shape. There is another answer which shows how this is done.

    • However, if you want the shape to be filled with the image then it sounds like we are just talking about taking a "bite" out of the image. This can be done with an overlay.

    For the overlay approach, you might want the size of the bite to depend on the width of the image. A GeometryReader can be used to measure this.

    Like this:

    Image("BGImage")
        .resizable()
        .scaledToFill()
        .overlay {
            GeometryReader { proxy in
                let w = proxy.size.width
                Circle()
                    .fill(Color(UIColor.systemBackground))
                    .frame(width: w * 1.8)
                    .offset(x: -w * 0.4, y: -w * 0.8)
                    .fixedSize()
            }
        }
        .frame(height: 250)
        .clipped()
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search