How to draw a gradient arc with Core Graphics/iPhone?

Viewed 8424

I know how to draw a arc

and I also found how to draw a gradient line from here

I have found two function can draw gradient:CGContextDrawLinearGradient and CGContextDrawRadialGradient.but how can I draw a gradient arc? I want to realize like this picture:enter image description here

3 Answers

A swift4 version of Derekahc's answer, and provided more options. check the picture and see what you want~

private func demoGradientCircle()->UIImage?{
    let imageSize = CGSize(width:1100, height:1100)
    UIGraphicsBeginImageContext(imageSize)
    guard let context = UIGraphicsGetCurrentContext() else{ return nil}

    //Set a white background
    context.setFillColor(UIColor.white.cgColor)
    context.fill(CGRect(origin:CGPoint(x:0, y:0), size:imageSize))
    context.setLineWidth(10)

    //Set up gradient
    let colorSpace = CGColorSpaceCreateDeviceRGB()
    //  use pure red green blue as the gradient color
    let colorCompoents1:[CGFloat] = [1, 0, 0, 1,
                                     0, 1, 0, 1,
                                     0, 0, 1, 1]
    let locations1:[CGFloat] = [0,0.5,1]
    let gradient1 = CGGradient(colorSpace: colorSpace, colorComponents: colorCompoents1,
                               locations: locations1, count: locations1.count)!

    //Option 1, do linear gradient once, and you'll get the circle on the left side
    let radius:CGFloat = 100
    let centerPointForCircle1 = CGPoint(x:250, y:550)
    context.addArc(center: centerPointForCircle1, radius: radius, startAngle: 0, endAngle:  CGFloat(Double.pi*2), clockwise: true)
    context.replacePathWithStrokedPath()
    context.saveGState()
    context.clip()
    context.drawLinearGradient(gradient1, start: CGPoint(x:150, y:550), end: CGPoint(x:350, y:550), options: [.drawsBeforeStartLocation, .drawsAfterEndLocation])

    //Option 2, if a 3 quarters circle would be enough for you, this will be a better solution(see the circles in the middle), but if you want a perfect gradient circle see Option 3
    context.restoreGState()
    let centerPointForCircle2 = CGPoint(x:550, y:550)
    context.addArc(center: centerPointForCircle2, radius: radius, startAngle: 0, endAngle:  CGFloat(Double.pi*2), clockwise: true)
    context.replacePathWithStrokedPath()
    context.saveGState()
    context.clip()
    let startCenterForCircle2 = CGPoint(x:centerPointForCircle2.x + radius, y:centerPointForCircle2.y)
    let endCenterForCircle2 = CGPoint(x:centerPointForCircle2.x, y:centerPointForCircle2.y - radius / 2)
    context.drawRadialGradient(gradient1, startCenter: startCenterForCircle2, startRadius: radius * 2, endCenter: endCenterForCircle2, endRadius: radius / 2, options: [.drawsBeforeStartLocation, .drawsAfterEndLocation])

    context.restoreGState()
    let centerPointForCircle3 = CGPoint(x:550, y:850)
    context.addArc(center: centerPointForCircle3, radius: radius, startAngle: CGFloat(-Double.pi*0.9), endAngle:  CGFloat(-Double.pi/2), clockwise: true)
    context.replacePathWithStrokedPath()
    context.saveGState()
    context.clip()
    let startCenterForCircle3 = CGPoint(x:centerPointForCircle3.x + radius, y:centerPointForCircle3.y)
    let endCenterForCircle3 = CGPoint(x:centerPointForCircle3.x, y:centerPointForCircle3.y - radius / 2)
    context.drawRadialGradient(gradient1, startCenter: startCenterForCircle3, startRadius: radius * 2, endCenter: endCenterForCircle3, endRadius: radius / 2, options: [.drawsBeforeStartLocation, .drawsAfterEndLocation])

    //Option 3, divide the circle into 3 parts(it depends on how many colors you want to use), and do linear gradient respectively. You may have to do some math work to calculate the points.A little bit complex but a perfect gradient circle, see the circle on the right side
    context.restoreGState()
    let centerPointForCircle4 = CGPoint(x:850, y:550)
    context.addArc(center: centerPointForCircle4, radius: radius, startAngle: CGFloat(Double.pi), endAngle:  CGFloat(Double.pi*5/3), clockwise: false)
    context.replacePathWithStrokedPath()
    context.saveGState()
    context.clip()

    let colorCompoents2:[CGFloat] = [1, 0, 0, 1,
                                     0, 1, 0, 1]
    let locations2:[CGFloat] = [0,1]
    let gradient2 = CGGradient(colorSpace: colorSpace, colorComponents: colorCompoents2,
                               locations: locations2, count: locations2.count)!

    context.drawLinearGradient(gradient2, start: CGPoint(x:750, y:550), end: CGPoint(x:900, y:463), options: [.drawsBeforeStartLocation, .drawsAfterEndLocation])

    context.restoreGState()
    context.addArc(center: centerPointForCircle4, radius: radius, startAngle: CGFloat(Double.pi*5/3), endAngle:  CGFloat(Double.pi*7/3), clockwise: false)
    context.replacePathWithStrokedPath()
    context.saveGState()
    context.clip()

    let colorCompoents3:[CGFloat] = [0, 1, 0, 1,
                                     0, 0, 1, 1]
    let gradient3 = CGGradient(colorSpace: colorSpace, colorComponents: colorCompoents3,
                               locations: locations2, count: locations2.count)!
    context.drawLinearGradient(gradient3, start: CGPoint(x:900, y:463), end: CGPoint(x:900, y:637), options: [.drawsBeforeStartLocation, .drawsAfterEndLocation])

    context.restoreGState()
    context.addArc(center: centerPointForCircle4, radius: radius, startAngle: CGFloat(Double.pi*7/3), endAngle:  CGFloat(Double.pi), clockwise: false)
    context.replacePathWithStrokedPath()
    context.saveGState()
    context.clip()

    let colorCompoents4:[CGFloat] = [0, 0, 1, 1,
                                     1, 0, 0, 1]
    let gradient4 = CGGradient(colorSpace: colorSpace, colorComponents: colorCompoents4,
                               locations: locations2, count: locations2.count)!
    context.drawLinearGradient(gradient4, start: CGPoint(x:900, y:637), end: CGPoint(x:750, y:550), options: [.drawsBeforeStartLocation, .drawsAfterEndLocation])

    let finalImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return finalImage
}

enter image description here

Related