ios – How to draw lines at an angle & arc in SwiftUI


Instead of doing the math to figure out how to draw the arc, I would just use subtracting to “subtract” the circle from a right-angled triangle.

struct Beak: Shape {
    let radius: CGFloat // this is the radius of the circle to be subtracted
    let angle: Angle
    func path(in rect: CGRect) -> Path {
        // first draw a right-angled triangle where the two short edges
        // intersect at the middle of rect
        var path = Path()
        path.move(to: CGPoint(x: rect.midX, y: rect.midY))
        path.addLine(to: CGPoint(x: rect.minX, y: rect.midY))
        let ratio = tan(angle.radians)
        let height = ratio * rect.width / 2
        path.addLine(to: CGPoint(x: rect.midX, y: rect.midY - height))
        path.closeSubpath()

        // then create the circle
        let circle = Path(ellipseIn: CGRect(
            x: rect.midX - radius,
            y: rect.midY - radius,
            width: radius * 2,
            height: radius * 2
        ))
        return path.subtracting(circle)
    }
}

Then the beak and body can be combined like this:

var body: some View {
    ZStack {
        // MARK: Body
        Circle()
            .fill(.yellow)
            .overlay(alignment: .center) {
                Circle()
                    .stroke(lineWidth: 5)
            }
            .frame(width: 150)
        
        // MARK: Beak
        Beak(radius: 75, angle: .degrees(16))
            .stroke(style: .init(lineWidth: 5, lineJoin: .round))
            .frame(width: 295, height: 295)
        
    }
    .frame(width: 300, height: 300)
    .background(.orange)
}

Notes:

  • I put the stroked circle above the filled circle to make it easier to reason about where the circle’s stroke is, and how thick it is, making aligning the strokes of the two paths easier.
  • I used a .round line join to stroke the beak, because a miter join looks terrible
  • I made the frame of the beak slightly smaller, so that the stroke doesn’t go beyond the orange background.

Output:

enter image description here

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img