Search code examples
iosxcodeswiftuipathuibezierpath

BezierPath clipShape issue


I added curves on the right and left sides. When you look at the stroke function, everything is normal, but when the stroke function is removed, the curve on the right works normally, but the curve on the left does not work. is this a bug?

ContentView

struct ContentView: View {
    @State var viewState: CGSize = .zero
    var body: some View {
        ZStack {
            Color.orange
                .clipShape(FooBezierPath(rightOffset: viewState).stroke())//remove stroke
                .edgesIgnoringSafeArea(.all)
                .overlay(
                    HStack {
                        Image(systemName: "chevron.right")
                            .font(.largeTitle)
                            .offset(y: 115)
                            .edgesIgnoringSafeArea(.all)
                        Spacer()
                        Image(systemName: "chevron.left")
                            .font(.largeTitle)

                            .contentShape(Rectangle())
                            .gesture(DragGesture().onChanged({ (value) in

                                withAnimation(.spring(response: 0.5, dampingFraction: 0.6, blendDuration: 0)) {
                                    self.viewState = value.translation
                                }
                            }).onEnded({ (value) in
                                withAnimation(.spring(response: 0.5, dampingFraction: 0.6, blendDuration: 0)) {
                                    self.viewState = .zero
                                }
                            }))
                            .edgesIgnoringSafeArea(.all)
                            .offset(y: 70)
                    }
                    ,alignment: .topTrailing
                )
                .padding(.horizontal)
           
        }
    }
}

BezierPath

struct FooBezierPath: Shape {
    var rightOffset: CGSize
    func path(in rect: CGRect) -> Path {
        return Path { path in
            let width = rect.width + rightOffset.width
            let height = rect.height
            
            path.move(to: CGPoint(x: 0, y: 0))
            path.addLine(to: CGPoint(x: rect.width, y: 0))
            path.addLine(to: CGPoint(x: rect.width, y: rect.height))
            path.addLine(to: CGPoint(x: 0, y: rect.height))
            path.addLine(to: CGPoint(x: 0, y: 0))
            
            
            //MARK: - Left Curve
            path.move(to: CGPoint(x: 0, y: 80))
            path.addCurve(to: CGPoint(x: 0, y: 180), control1: CGPoint(x: 50, y: 130), control2: CGPoint(x: 50, y: 130))
            
            //MARK: - Right Curve
            path.move(to: CGPoint(x: width, y: 80))
            path.addCurve(to: CGPoint(x: width, y: 180), control1: CGPoint(x: width - 50, y: 130), control2: CGPoint(x: width - 50, y: 130))
        }
    }
}

enter image description here

enter image description here


Solution

  • It Helps to Draw the entire shape without moving points, otherwise the clip malfunctions for some reason. Try this:

    struct FooBezierPath: Shape {
        var rightOffset: CGSize
        func path(in rect: CGRect) -> Path {
            return Path { path in
                let width = rect.width + rightOffset.width
                let height = rect.height
                
                // Draw left Edge of Shape
                path.move(to: CGPoint(x: 0, y: 0))
                path.addLine(to: CGPoint(x: 0, y: 80))
                path.addCurve(to: CGPoint(x: 0, y: 180), control1: CGPoint(x: 50, y: 130), control2: CGPoint(x: 50, y: 130))
                path.addLine(to: CGPoint(x: 0, y: height))
                
                // Draw Bottom Edge of Shape
                path.addLine(to: CGPoint(x: width, y: height))
                
                // Draw Right Edge of Shape
                path.addLine(to: CGPoint(x: width, y: 180))
                path.addCurve(to: CGPoint(x: width, y: 80), control1: CGPoint(x: width - 50, y: 130), control2: CGPoint(x: width - 50, y: 130))
                path.addLine(to: CGPoint(x: width, y: 0))
                
                // Draw Top Edge of Shape
                path.addLine(to: CGPoint(x:0, y: 0))
            }
        }
    }
    

    Tried and tested the code, the results are:

    1. Without Stroke

    Without Stroke

    1. With Stroke

    enter image description here