Search code examples
iosobjective-ciphonecocoa-touchuikit

Fill UIBezierPath with parallel lines


I'm trying to draw custom shape using UIBezierPath:

UIBezierPath *aPath = [UIBezierPath bezierPath];

    [aPath moveToPoint:CGPointMake(100.0, 0.0)];

    // Draw the lines.
    [aPath addLineToPoint:CGPointMake(200.0, 40.0)];
    [aPath addLineToPoint:CGPointMake(160, 140)];
    [aPath addLineToPoint:CGPointMake(40.0, 140)];
    [aPath addLineToPoint:CGPointMake(0.0, 40.0)];
    [aPath closePath];

I want to fill it with parallel lines to make this stripped. I want to change color of this lines too. Assume that I want to make them vertical. I have to calculate somehow points on this path with regular interval, how I can do this?

I have found this UIColor colorWithPatternImage but then i cant change color and "density" of my lines inside shape.


Solution

  • Like Nikolai Ruhe said, the best option is to use your shape as the clipping path, and then draw some pattern inside the bounding box of the shape. Here's an example of what the code would look like

    - (void)drawRect:(CGRect)rect
    {
        // create a UIBezierPath for the outline shape
        UIBezierPath *aPath = [UIBezierPath bezierPath];
        [aPath moveToPoint:CGPointMake(100.0, 0.0)];
        [aPath addLineToPoint:CGPointMake(200.0, 40.0)];
        [aPath addLineToPoint:CGPointMake(160, 140)];
        [aPath addLineToPoint:CGPointMake(40.0, 140)];
        [aPath addLineToPoint:CGPointMake(0.0, 40.0)];
        [aPath closePath];
        [aPath setLineWidth:10];
    
        // get the bounding rectangle for the outline shape
        CGRect bounds = aPath.bounds;
    
        // create a UIBezierPath for the fill pattern
        UIBezierPath *stripes = [UIBezierPath bezierPath];
        for ( int x = 0; x < bounds.size.width; x += 20 )
        {
            [stripes moveToPoint:CGPointMake( bounds.origin.x + x, bounds.origin.y )];
            [stripes addLineToPoint:CGPointMake( bounds.origin.x + x, bounds.origin.y + bounds.size.height )];
        }
        [stripes setLineWidth:10];
    
        CGContextRef context = UIGraphicsGetCurrentContext();
    
        // draw the fill pattern first, using the outline to clip
        CGContextSaveGState( context );         // save the graphics state
        [aPath addClip];                        // use the outline as the clipping path
        [[UIColor blueColor] set];              // blue color for vertical stripes
        [stripes stroke];                       // draw the stripes
        CGContextRestoreGState( context );      // restore the graphics state, removes the clipping path
    
        // draw the outline of the shape
        [[UIColor greenColor] set];             // green color for the outline
        [aPath stroke];                         // draw the outline
    }
    

    Using Swift

    override func draw(_ rect: CGRect){
    
            // create a UIBezierPath for the outline shape
            let aPath = UIBezierPath()
            aPath.move(to: CGPoint(x: 100.0, y: 0.0))
            aPath.addLine(to: CGPoint(x: 200.0, y: 40.0))
            aPath.addLine(to: CGPoint(x: 160, y: 140))
            aPath.addLine(to: CGPoint(x: 40.0, y: 140))
            aPath.addLine(to: CGPoint(x: 0.0, y: 40.0))
            aPath.close()
            aPath.lineWidth = 10
    
            // get the bounding rectangle for the outline shape
            let bounds = aPath.bounds
    
            // create a UIBezierPath for the fill pattern
            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
    
            let context = UIGraphicsGetCurrentContext()
    
            // draw the fill pattern first, using the outline to clip
            context!.saveGState()         // save the graphics state
            aPath.addClip()                        // use the outline as the clipping path
            UIColor.blue.set()                    // blue color for vertical stripes
            stripes.stroke()                       // draw the stripes
            context!.restoreGState()      // restore the graphics state, removes the clipping path
    
            // draw the outline of the shape
            UIColor.green.set()             // green color for the outline
            aPath.stroke()                         // draw the outline
        }
    

    Produces

    enter image description here