Search code examples
iosswiftuikituibezierpathcurve

Clipping the bezier path in curve shape


I using Swift to creating a custom button in a phone UI and need to clip the bottom of the button in the convex like shape.

Like this

The problem was it should be perfect and the bottom curve should match the bigger button

Like this

I tried different approaches but it's not getting the perfect result.

  1. Using rounded corners

    if buttonDirection == 0 {
        path = UIBezierPath(roundedRect: rect, byRoundingCorners:[UIRectCorner.topLeft, .topRight], cornerRadii: CGSize(width: self.bounds.width/2, height: 0))
        path.close()  
    }
    
  2. Create whole path without rounded curve using QuardCurve // still bottom part not inverse curve plus corner are also not smooth as 1

     if buttonDirection == 0 {
           //path = UIBezierPath(roundedRect: rect, byRoundingCorners:[UIRectCorner.topLeft, .topRight], cornerRadii: CGSize(width: self.bounds.width/2, height: 0))
          //path.close()
            let curve = UIBezierPath()
            curve.move(to: CGPoint(x: 0, y: self.bounds.height))
            curve.addLine(to:CGPoint(x: 0, y: self.bounds.width/3))
            curve.addQuadCurve(to: CGPoint(x: self.bounds.width, y: self.bounds.width/3), controlPoint: CGPoint(x: self.bounds.width/2, y: -5))
            curve.addLine(to: CGPoint(x: self.bounds.width, y: self.bounds.height))
            curve.addQuadCurve(to: CGPoint(x: 0, y: self.bounds.height), controlPoint: CGPoint(x: self.bounds.width/2, y: self.bounds.width - 10))
            UIColor.black.setFill()
            curve.fill()
        }
    
  3. Create the path from 1 and then just Clip QuardCurve

    if buttonDirection == 0 {
        path = UIBezierPath(roundedRect: rect, byRoundingCorners:[UIRectCorner.topLeft, .topRight], cornerRadii: CGSize(width: self.bounds.width/2, height: 0))
        path.close()
        path.move(to: CGPoint(x: 0, y: self.bounds.height))
        path.addQuadCurve(to: CGPoint(x: self.bounds.width, y: self.bounds.height), controlPoint: CGPoint(x: self.bounds.width/2, y: self.bounds.height/2))
        path.addClip()
        UIColor.black.setFill()
        path.fill()
    } 
    

I tried many other things also but not getting the result, What I wanted is simply clip the bottom curve from the 1st path, Like how to cut one path from another (After reading apples doc I come to know I can use path.reverse() also )

here are all buttons in one pic and when you click the button say vol + its changes the colour

All four buttons vol+, vol-, ch+,ch- and centre button(which itself is subdivided in five-part :-pc)

PS Edited the original question, as images were confusing, and I found one solution but still want to know if there is a better solution with one path and smooth edges.


Solution

  • Below method worked but if someone has better solution do post. Basically what I am doing here is first clipping the whole button with the bottom part as convex, using addLines and Quardcurve in the bottom and after that creating new path using bezier roundedRect initialization with top-right and top-left corner.

    if buttonDirection == 0 {
         let curve = UIBezierPath()
         curve.move(to: CGPoint(x: 0, y: self.bounds.height))
         curve.addLine(to: CGPoint(x: 0, y: 0))
         curve.addLine(to: CGPoint(x: self.bounds.width, y: 0))
         curve.addLine(to: CGPoint(x: self.bounds.width, y: self.bounds.height))
         curve.addQuadCurve(to: CGPoint(x: 0, y: self.bounds.height), controlPoint: CGPoint(x: self.bounds.width/2, y: self.bounds.height - self.bounds.height/4))
         curve.close()
         curve.addClip()
         path = UIBezierPath(roundedRect: rect, byRoundingCorners:[UIRectCorner.topLeft, .topRight], cornerRadii: CGSize(width: self.bounds.width/2, height: 0))
         path.close()
    }