Adam Carter
Adam Carter

Reputation: 4844

CoreGraphics - Draw stroke of arc

I have a UIBezierPath which is an arc. I only want to draw the stroke to the graphics context (that is, the stroke of the arc, NOT including the line connecting the end and start points of the arc)

Once I’ve done that, I can then add a linear gradient to the context, effectively drawing a gradient on the stroke of an arc.

Here is my drawRect:

    let context = UIGraphicsGetCurrentContext()

    CGContextSaveGState(context)
    CGContextAddPath(context, _progressPathForProgress(_progressToDrawForProgress(progress)).CGPath)
    CGContextStrokePath(context)
    CGContextClip(context)

    let colours = [self.startColour.CGColor, self.endColour.CGColor]
    let colourSpace = CGColorSpaceCreateDeviceRGB()
    let colourLocations: [CGFloat] = [0.0, 1.0]

    let gradient = CGGradientCreateWithColors(colourSpace, colours, colourLocations)

    var startPoint = CGPoint.zeroPoint
    var endPoint = CGPoint(x: 0, y: bounds.height)
    CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, CGGradientDrawingOptions.allZeros)

    CGContextRestoreGState(context)

But all this does is add a gradient to the entirety of my UIView. Where have I gone wrong?

Upvotes: 0

Views: 702

Answers (1)

zisoft
zisoft

Reputation: 23078

The path needs to be closed in order to get the clipping to work.

If you don't want to see the closing line you can set the stroke color to UIColor.clearColor() and then close the path.

CGContextSaveGState(context)
CGContextAddPath(context, _progressPathForProgress(_progressToDrawForProgress(progress)).CGPath)
CGContextStrokePath(context)

CGContextSetStrokeColorWithColor(context, UIColor.clearColor().CGColor)

// close the path, you will need to add some more points here, otherwise
// the end point is simply connected to the start point
CGPathCloseSubpath(...)

CGContextClip(context)

// draw the gradient

I'll explain what I mean by adding more points to close the path. The following images are a screenshot from one of my apps, it is an altitude profile with a gradient below the graph.

enter image description here

Closing the path directly would result in this, meaning the gradient would not be drawn down to the x-axis:

enter image description here

To close the path correctly I add points from the last coordinate (x,y) down to the x axis (x,0), then to (0,0) and finally close the path with the first point, like so:

enter image description here

I don't want to see the closing lines, so I use UIColor.clearColor() here.

Hope you get the idea.

Upvotes: 1

Related Questions