Search code examples
iosswiftuibezierpath

Fill a UIBezierPath shape with stripes


I have a class that draws a circle inside of a view. I know how to fill the circle, and I know how to have the circle only be an outline.

I want to fill the circle with stripes, so that the below circle would look like the outline with alternating stripes of red and white, but the white stripes would only look white against a white background because they would represent the lack a colour fill.

import UIKit

@IBDesignable
class Circle: UIView{
    override func draw(_ rect: CGRect){
        let radius = bounds.width / 4
        let centerY = (bounds.maxY - bounds.minY) / 2
        let centerX = (bounds.maxX - bounds.minX)/2
        let centerPoint = CGPoint(x: centerX, y: centerY)
        drawCircle(radius: radius, center: centerPoint)

    }

    private func drawCircle(radius: CGFloat, center: CGPoint){
        let path = UIBezierPath()
        path.addArc(withCenter: center, radius: radius, startAngle: 0, endAngle: 2*CGFloat.pi, clockwise: true)
        path.close()
        UIColor.red.set()
        path.lineWidth = 5.0
        path.stroke()
        //path.fill()
    }
}

enter image description here


Solution

  • Solution using clipping regions

    import UIKit
    
    @IBDesignable
    class Circle: UIView{
        override func draw(_ rect: CGRect){
            let radius = bounds.width / 4
            let centerY = (bounds.maxY - bounds.minY) / 2
            let centerX = (bounds.maxX - bounds.minX)/2
            let centerPoint = CGPoint(x: centerX, y: centerY)
            drawCircle(radius: radius, center: centerPoint)
        }
        
        private func drawCircle(radius: CGFloat, center: CGPoint){
            let path = UIBezierPath()
            path.addArc(withCenter: center, radius: radius, startAngle: 0, endAngle: 2*CGFloat.pi, clockwise: true)
            path.close()
            UIColor.red.set()
            path.lineWidth = 5.0
    
            //////////////////////////The part the produces stripes ////////////////////
            let bounds = path.bounds
            
            let stripes = UIBezierPath()
            for x in stride(from: 0, to: bounds.size.width, by: 20){
                stripes.move(to: CGPoint(x: bounds.origin.x + x, y: bounds.origin.y ))
                stripes.addLine(to: CGPoint(x: bounds.origin.x + x, y: bounds.origin.y + bounds.size.height ))
            }
            stripes.lineWidth = 10
    
            path.addClip()
            stripes.stroke()        
            //////////////////////////////////////////////////////////////////////////
            path.stroke()
        }
    }
    

    enter image description here