Search code examples
swiftcore-graphicsuibezierpathcagradientlayer

Applying gradient layer over a UIBezierPath graph


This is my first time asking a question, so pardon me if it not very thorough.

Basically I am trying to apply a gradient layer on top of a UIBezierPath that is drawn as a graph.

Here is my graph:

normal graph

Here is the gradient layer I am going for:

gradient graph

Here is what I have tried to draw my graph:

let path = quadCurvedPathWithPoints(points: points)
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
shapeLayer.strokeColor = UIColor.blue.cgColor
shapeLayer.fillColor = UIColor.white.cgColor
shapeLayer.position = CGPoint(x: 0, y: 0)
shapeLayer.lineWidth = 1.0

This fills the graph with a blue stroke, obviously, but now I am trying to apply the white to green gradient. The way I am doing it is not working. Here is the result:

fail gradient graph

Here is the code I am struggling with:

let startColor = UIColor.white.withAlphaComponent(0.5)
let endColor = UIColor.green

let gradient = CAGradientLayer()
gradient.colors = [startColor.cgColor, endColor.cgColor]
gradient.startPoint = CGPoint(x: 0.0, y: 0.5)
gradient.endPoint = CGPoint(x: 1.0, y: 0.5)
gradient.frame = path.bounds
let shapeMask = CAShapeLayer()
shapeMask.path = path.cgPath
gradient.mask = shapeLayer
sparkLineView.layer.addSublayer(gradient)

Solution

  • Here's a little demo that draws a UIBezierPath path using a gradient. You can copy this into a Swift playground.

    class GradientGraph: UIView {
        override func draw(_ rect: CGRect) {
            // Create the "graph"
            let path = UIBezierPath()
            path.move(to: CGPoint(x: 0, y: frame.height * 0.5))
            path.addLine(to: CGPoint(x: frame.width * 0.2, y: frame.height * 0.3))
            path.addLine(to: CGPoint(x: frame.width * 0.4, y: frame.height * 0.8))
            path.addLine(to: CGPoint(x: frame.width * 0.6, y: frame.height * 0.4))
            path.addLine(to: CGPoint(x: frame.width * 0.8, y: frame.height * 0.7))
    
            // Create the gradient
            let gradient = CGGradient(colorsSpace: nil, colors: [UIColor.white.cgColor,UIColor.green.cgColor] as CFArray, locations: nil)!
    
            // Draw the graph and apply the gradient
            let ctx = UIGraphicsGetCurrentContext()!
            ctx.setLineWidth(6)
    
            ctx.saveGState()
            ctx.addPath(path.cgPath)
            ctx.replacePathWithStrokedPath()
            ctx.clip()
            ctx.drawLinearGradient(gradient, start: CGPoint(x: 0, y: 0), end: CGPoint(x: frame.width, y: 0), options: [])
            ctx.restoreGState()
        }
    }
    
    let graph = GradientGraph(frame: CGRect(x: 0, y: 0, width: 700, height: 700))