skip to Main Content

I am making an app where I need to use half circle. But I can’t make its frame match the real size of the object. Right now I am trimming the circle but I don’t really know you to actually crop the view.

Here is how I trimming the circle:

Circle()
   .trim(from: 0, to: 0.5)
   .fill(Color.blue)
   .background(Color.red)

And I am getting colour red as background twice bigger the my new object.

2

Answers


  1. It’s probably better to make your own HalfCircle that conforms to Shape instead of trying to bash Circle into the shape you need. Let’s go the extra mile and make it conform to InsettableShape, in case you want to use it to stroke a border.

    import SwiftUI
    
    struct HalfCircle: InsettableShape {
        var _inset: CGFloat = 0
    
        func inset(by amount: CGFloat) -> Self {
            var copy = self
            copy._inset += amount
            return copy
        }
    
        func path(in rect: CGRect) -> Path {
            var path = Path()
    
            // This is a half-circle centered at the origin with radius 1.
            path.addArc(
                center: .zero,
                radius: 1,
                startAngle: .zero,
                endAngle: .radians(.pi),
                clockwise: false
            )
            path.closeSubpath()
    
            // Since it's the bottom half of a circle, we only want
            // to inset the left, right, and bottom edges of rect.
            let rect = rect
                .insetBy(dx: _inset, dy: 0.5 * _inset)
                .offsetBy(dx: 0, dy: -(0.5 * _inset))
    
            // This transforms bounding box of the path to fill rect.
            let transform = CGAffineTransform.identity
                .translatedBy(x: rect.origin.x + 0.5 * rect.size.width, y: 0)
                .scaledBy(x: rect.width / 2, y: rect.height)
    
            return path.applying(transform)
        }
    }
    

    We can use it to draw this:

    the bottom half of a circle

    using this playground:

    import PlaygroundSupport
    
    PlaygroundPage.current.setLiveView(HalfCircle()
        .inset(by: 20)
        .fill(.black)
        .background(.gray)
        .aspectRatio(2, contentMode: .fit)
        .frame(width: 200)
        .padding()
    )
    
    Login or Signup to reply.
  2. You can mask it differently using a GeometryReader:

    GeometryReader { proxy in
        Circle()
            .fill(.blue)
            .offset(y: -proxy.size.height) // <- Shows bottom part
            .frame(height: proxy.size.width) // <- Makes the circle match frame
            .background(.red) // <- Just for testing
    }
    .aspectRatio(2, contentMode: .fit) // <- Makes the frame ration 2 : 1 (landscape rectangle)
    .clipped() // <- Removes out of bound drawings
    

    Demo

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search