Search code examples
iosswiftuibezierpath

UIBezierPath Star with rounded corners


I have created a star shape image by UIBezierPath using this code:

    let path = UIBezierPath()
    let center = CGPoint(x: rect.width / 2.0, y: rect.height / 2.0)
    let xCenter: CGFloat = center.x
    let yCenter: CGFloat = center.y
    let w = rect.width
    let r = w / 2.0
    let flip: CGFloat = -1.0 // use this to flip the figure 1.0 or -1.0
    let polySide = CGFloat(5)
    let theta = 2.0 * Double.pi * Double(2.0 / polySide)
    path.move(to: CGPoint(x: xCenter, y: r * flip + yCenter))
    for i in 1..<Int(polySide) {
        let x: CGFloat = r * CGFloat( sin(Double(i) * theta) )
        let y: CGFloat = r * CGFloat( cos(Double(i) * theta) )
        path.addLine(to: CGPoint(x: x + xCenter, y: y * flip + yCenter))
    }
    path.close()

enter image description here

And I want to give corner radius to each corner of the star. I tried smth but I could not figure it out. Can you help me to do this?


Solution

  • Here is a custom UIView that computes a path for a 5-point star with a cornerRadius:

    class RoundedStar : UIView {
        var cornerRadius: CGFloat = 10 { didSet { setNeedsDisplay() } }
        var rotation: CGFloat = 54     { didSet { setNeedsDisplay() } }
        var fillColor = UIColor.red    { didSet { setNeedsDisplay() } }
    
        override func draw(_ rect: CGRect) {
            let path = UIBezierPath()
            let center = CGPoint(x: rect.width / 2, y: rect.height / 2)
            let r = rect.width / 2
            let rc = cornerRadius
            let rn = r * 0.95 - rc
    
            var cangle = rotation
            for i in 1 ... 5 {
                // compute center point of tip arc
                let cc = CGPoint(x: center.x + rn * cos(cangle * .pi / 180), y: center.y + rn * sin(cangle * .pi / 180))
    
                // compute tangent point along tip arc
                let p = CGPoint(x: cc.x + rc * cos((cangle - 72) * .pi / 180), y: cc.y + rc * sin((cangle - 72) * .pi / 180))
    
                if i == 1 {
                    path.move(to: p)
                } else {
                    path.addLine(to: p)
                }
    
                // add 144 degree arc to draw the corner
                path.addArc(withCenter: cc, radius: rc, startAngle: (cangle - 72) * .pi / 180, endAngle: (cangle + 72) * .pi / 180, clockwise: true)
    
                cangle += 144
            }
    
            path.close()
            fillColor.setFill()
            path.fill()
        }
    }
    

    Example run in the Playground:

    enter image description here


    Simulator Demo

    enter image description here

    Code:

    class ViewController: UIViewController {
    
        @IBOutlet weak var rstar: RoundedStar!
        @IBOutlet weak var cornerRadiusLabel: UILabel!
        @IBOutlet weak var rotationlabel: UILabel!
    
        @IBAction func cornerRadiusChanged(_ sender: UISlider) {
            rstar.cornerRadius = CGFloat(sender.value)
            cornerRadiusLabel.text = "Corner Radius: \(Int(sender.value))"
        }
    
        @IBAction func rotationChanged(_ sender: UISlider) {
            rstar.rotation = CGFloat(sender.value)
            rotationlabel.text = "Rotation: \(Int(sender.value))"
        }
    }