Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS - Circle shaped gradient

Tags:

ios

swift

I am trying to draw a circular shaped gradient.

let backgroundView:UIView = UIView()
let backgroundLayer:CAShapeLayer = CAShapeLayer()
let gradient:CAGradientLayer = CAGradientLayer()
...

backgroundLayer.frame = CGRectMake(0, 0, backgroundDiameter, backgroundDiameter)
backgroundLayer.backgroundColor = UIColor.clearColor().CGColor
backgroundLayer.strokeColor = backgroundStrokeColor
backgroundLayer.fillColor = backgroundFillColor


gradient.colors = [UIColor(red: 0.5, green: 0.5, blue: 0.9, alpha: 1.0).CGColor,  
UIColor(red: 0.9, green: 0.9, blue: 0.3, alpha: 1.0).CGColor]
gradient.locations = [0.01, 0.8]
gradient.frame = backgroundLayer.frame

backgroundView.frame = CGRectMake(0, 0, backgroundDiameter, backgroundDiameter)
backgroundView.backgroundColor = UIColor.clearColor()
backgroundView.center = ringControlCenter
backgroundLayer.insertSublayer(gradient, atIndex: 1)
backgroundLayer.path = CGPathCreateWithEllipseInRect(backgroundLayer.frame, nil)

backgroundView.layer.addSublayer(backgroundLayer)
self.addSubview(backgroundView)

However the gradient does not seem to be impacted by:

backgroundLayer.path = CGPathCreateWithEllipseInRect(backgroundLayer.frame, nil)

And still have its initial shape. Is there a way to mask the gradient with an ellipse shaped layer without using CGContext* instructions?

Thank you,

MG

like image 447
user3817688 Avatar asked Jul 09 '14 14:07

user3817688


3 Answers

Here is Leo's library converted to Swift 3. Thanks to Alessandro Ornano's Swift 2.3 translation.

Code:

import UIKit

class WCGraintCircleLayer: CALayer {

  override init () {
    super.init()
  }

  convenience init(bounds:CGRect,position:CGPoint,fromColor:UIColor,toColor:UIColor,linewidth:CGFloat,toValue:CGFloat) {
    self.init()
    self.bounds = bounds
    self.position = position
    let colors : [UIColor] = self.graintFromColor(fromColor: fromColor, toColor:toColor, count:4)
    for i in 0..<colors.count-1 {
      let graint = CAGradientLayer()
      graint.bounds = CGRect(x: 0, y: 0, width: bounds.width/2, height: bounds.height/2)
      let valuePoint = self.positionArrayWithMainBounds(bounds: self.bounds)[i]
      graint.position = valuePoint
      print("iesimo graint position: \(graint.position)")
      let fromColor = colors[i]
      let toColor = colors[i+1]
      let colors : [CGColor] = [fromColor.cgColor,toColor.cgColor]
      let stopOne: CGFloat = 0.0
      let stopTwo: CGFloat = 1.0
      let locations : [CGFloat] = [stopOne,stopTwo]
      graint.colors = colors
      graint.locations = locations as [NSNumber]?
      graint.startPoint = self.startPoints()[i]
      graint.endPoint = self.endPoints()[i]
      self.addSublayer(graint)
      //Set mask
      let shapelayer = CAShapeLayer()
      let rect = CGRect(x: 0, y: 0, width: bounds.width - 2 * linewidth, height: bounds.height - 2 * linewidth)
      shapelayer.bounds = rect
      shapelayer.position = CGPoint(x: bounds.width/2, y: bounds.height/2)
      shapelayer.strokeColor = UIColor.blue.cgColor
      shapelayer.fillColor = UIColor.clear.cgColor
      shapelayer.path = UIBezierPath(roundedRect: rect, cornerRadius: rect.width/2).cgPath
      shapelayer.lineWidth = linewidth
      shapelayer.lineCap = kCALineCapRound
      shapelayer.strokeStart = 0.010
      let finalValue = (toValue*0.99)
      shapelayer.strokeEnd = finalValue//0.99;
      self.mask = shapelayer
    }
  }

  required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }

  func layerWithWithBounds(bounds:CGRect, position:CGPoint, fromColor:UIColor, toColor:UIColor, linewidth : CGFloat,toValue:CGFloat) -> WCGraintCircleLayer {
    let layer = WCGraintCircleLayer(bounds: bounds,position: position,fromColor:fromColor, toColor: toColor,linewidth: linewidth,toValue:toValue )
    return layer
  }

  func graintFromColor(fromColor:UIColor, toColor:UIColor, count:Int) -> [UIColor]{
    var fromR:CGFloat = 0.0,fromG:CGFloat = 0.0,fromB:CGFloat = 0.0,fromAlpha:CGFloat = 0.0
    fromColor.getRed(&fromR,green: &fromG,blue: &fromB,alpha: &fromAlpha)

    var toR:CGFloat = 0.0,toG:CGFloat = 0.0,toB:CGFloat = 0.0,toAlpha:CGFloat = 0.0
    toColor.getRed(&toR,green: &toG,blue: &toB,alpha: &toAlpha)

    var result : [UIColor]! = [UIColor]()

    for i in 0...count {
      let oneR:CGFloat = fromR + (toR - fromR)/CGFloat(count) * CGFloat(i)
      let oneG : CGFloat = fromG + (toG - fromG)/CGFloat(count) * CGFloat(i)
      let oneB : CGFloat = fromB + (toB - fromB)/CGFloat(count) * CGFloat(i)
      let oneAlpha : CGFloat = fromAlpha + (toAlpha - fromAlpha)/CGFloat(count) * CGFloat(i)
      let oneColor = UIColor.init(red: oneR, green: oneG, blue: oneB, alpha: oneAlpha)
      result.append(oneColor)
      print(oneColor)

    }
    return result
  }

  func positionArrayWithMainBounds(bounds:CGRect) -> [CGPoint]{
    let first = CGPoint(x: (bounds.width/4)*3, y: (bounds.height/4)*1)
    let second = CGPoint(x: (bounds.width/4)*3, y: (bounds.height/4)*3)
    let third = CGPoint(x: (bounds.width/4)*1, y: (bounds.height/4)*3)
    let fourth = CGPoint(x: (bounds.width/4)*1, y: (bounds.height/4)*1)
    print([first,second,third,fourth])
    return [first,second,third,fourth]
  }

  func startPoints() -> [CGPoint] {
    return [CGPoint(x: 0, y: 0),CGPoint(x: 1, y: 0),CGPoint(x: 1, y: 1),CGPoint(x: 0, y: 1)]
  }

  func endPoints() -> [CGPoint] {
    return [CGPoint(x: 1, y: 1),CGPoint(x: 0, y: 1),CGPoint(x: 0, y: 0),CGPoint(x: 1, y: 0)]
  }

  func midColorWithFromColor(fromColor:UIColor, toColor:UIColor, progress:CGFloat) -> UIColor {
    var fromR:CGFloat = 0.0,fromG:CGFloat = 0.0,fromB:CGFloat = 0.0,fromAlpha:CGFloat = 0.0
    fromColor.getRed(&fromR,green: &fromG,blue: &fromB,alpha: &fromAlpha)

    var toR:CGFloat = 0.0,toG:CGFloat = 0.0,toB:CGFloat = 0.0,toAlpha:CGFloat = 0.0
    toColor.getRed(&toR,green: &toG,blue: &toB,alpha: &toAlpha)

    let oneR = fromR + (toR - fromR) * progress
    let oneG = fromG + (toG - fromG) * progress
    let oneB = fromB + (toB - fromB) * progress
    let oneAlpha = fromAlpha + (toAlpha - fromAlpha) * progress
    let oneColor = UIColor.init(red: oneR, green: oneG, blue: oneB, alpha: oneAlpha)
    return oneColor
  }

  // This is what you call if you want to draw a full circle.
  func animateCircle(duration: TimeInterval) {
    animateCircleTo(duration: duration, fromValue: 0.010, toValue: 0.99)
  }

  // This is what you call to draw a partial circle.
  func animateCircleTo(duration: TimeInterval, fromValue: CGFloat, toValue: CGFloat){
    // We want to animate the strokeEnd property of the circleLayer
    let animation = CABasicAnimation(keyPath: "strokeEnd")
    animation.isRemovedOnCompletion = true
    // Set the animation duration appropriately
    animation.duration = duration

    // Animate from 0.010 (no circle) to 0.99 (full circle)
    animation.fromValue = 0.010
    animation.toValue = toValue

    // Do an easeout. Don't know how to do a spring instead
    //animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
    animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)

    // Set the circleLayer's strokeEnd property to 0.99 now so that it's the
    // right value when the animation ends.
    let circleMask = self.mask as! CAShapeLayer
    circleMask.strokeEnd = toValue

    // Do the actual animation
    circleMask.removeAllAnimations()
    circleMask.add(animation, forKey: "animateCircle")
  }

}

How to use:

let gradientRingLayer = WCGraintCircleLayer(bounds: CGRect(x: 0, y: 0, width: 150, height: 150), position:CGPoint(x: 200, y: 300),fromColor:UIColor.blue, toColor:UIColor.white, linewidth:4.0, toValue:0)    
self.view.layer.addSublayer(gradientRingLayer)
let duration = 3.0
gradientRingLayer.animateCircleTo(duration: duration, fromValue: 0, toValue: 0.99)
like image 70
Tolgahan Arıkan Avatar answered Oct 01 '22 03:10

Tolgahan Arıkan


I've translated Leo library's in Swift 3.x , in other words , the good WCGradientCircleLayer writed in objective-C (it work exactly as aspected)

import UIKit

class WCGraintCircleLayer: CALayer {

    override init () {
        super.init()
    }

    convenience init(bounds:CGRect,position:CGPoint,fromColor:UIColor,toColor:UIColor,linewidth:CGFloat,toValue:CGFloat) {
        self.init()
        self.bounds = bounds
        self.position = position
        let colors : [UIColor] = self.graint(fromColor: fromColor, toColor:toColor, count:4)
        for i in 0..<colors.count-1 {
            let graint = CAGradientLayer()
            graint.bounds = CGRect(origin:CGPoint.zero, size: CGSize(width:bounds.width/2,height:bounds.height/2))
            let valuePoint = self.positionArrayWith(bounds: self.bounds)[i]
            graint.position = valuePoint
            print("iesimo graint position: \(graint.position)")
            let fromColor = colors[i]
            let toColor = colors[i+1]
            let colors : [CGColor] = [fromColor.cgColor,toColor.cgColor]
            let stopOne: CGFloat = 0.0
            let stopTwo: CGFloat = 1.0
            let locations : [CGFloat] = [stopOne,stopTwo]
            graint.colors = colors
            graint.locations = locations as [NSNumber]? // with Swift 2 and Swift 3 you can cast directly a `CGFloat` value to `NSNumber` and back
            graint.startPoint = self.startPoints()[i]
            graint.endPoint = self.endPoints()[i]
            self.addSublayer(graint)
            //Set mask
            let shapelayer = CAShapeLayer()
            let rect = CGRect(origin:CGPoint.zero,size:CGSize(width:self.bounds.width - 2 * linewidth,height: self.bounds.height - 2 * linewidth))
            shapelayer.bounds = rect
            shapelayer.position = CGPoint(x:self.bounds.width/2,y: self.bounds.height/2)
            shapelayer.strokeColor = UIColor.blue.cgColor
            shapelayer.fillColor = UIColor.clear.cgColor
            shapelayer.path = UIBezierPath(roundedRect: rect, cornerRadius: rect.width/2).cgPath
            shapelayer.lineWidth = linewidth
            shapelayer.lineCap = kCALineCapRound
            shapelayer.strokeStart = 0.010
            let finalValue = (toValue*0.99)
            shapelayer.strokeEnd = finalValue//0.99;
            self.mask = shapelayer
        }
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func layerWithWithBounds(bounds:CGRect, position:CGPoint, fromColor:UIColor, toColor:UIColor, linewidth : CGFloat,toValue:CGFloat) -> WCGraintCircleLayer {
        let layer = WCGraintCircleLayer(bounds: bounds,position: position,fromColor:fromColor, toColor: toColor,linewidth: linewidth,toValue:toValue )
        return layer
    }

    func graint(fromColor:UIColor, toColor:UIColor, count:Int) -> [UIColor]{
        var fromR:CGFloat = 0.0,fromG:CGFloat = 0.0,fromB:CGFloat = 0.0,fromAlpha:CGFloat = 0.0
        fromColor.getRed(&fromR,green: &fromG,blue: &fromB,alpha: &fromAlpha)

        var toR:CGFloat = 0.0,toG:CGFloat = 0.0,toB:CGFloat = 0.0,toAlpha:CGFloat = 0.0
        toColor.getRed(&toR,green: &toG,blue: &toB,alpha: &toAlpha)

        var result : [UIColor]! = [UIColor]()

        for i in 0...count {
            let oneR:CGFloat = fromR + (toR - fromR)/CGFloat(count) * CGFloat(i)
            let oneG : CGFloat = fromG + (toG - fromG)/CGFloat(count) * CGFloat(i)
            let oneB : CGFloat = fromB + (toB - fromB)/CGFloat(count) * CGFloat(i)
            let oneAlpha : CGFloat = fromAlpha + (toAlpha - fromAlpha)/CGFloat(count) * CGFloat(i)
            let oneColor = UIColor.init(red: oneR, green: oneG, blue: oneB, alpha: oneAlpha)
            result.append(oneColor)
            print(oneColor)

        }
        return result
    }

    func positionArrayWith(bounds:CGRect) -> [CGPoint]{
        let first = CGPoint(x:(bounds.width/4)*3,y: (bounds.height/4)*1)
        let second = CGPoint(x:(bounds.width/4)*3,y: (bounds.height/4)*3)
        let third = CGPoint(x:(bounds.width/4)*1,y: (bounds.height/4)*3)
        let fourth = CGPoint(x:(bounds.width/4)*1,y: (bounds.height/4)*1)
        print([first,second,third,fourth])
        return [first,second,third,fourth]
    }

    func startPoints() -> [CGPoint] {
        return [CGPoint.zero,CGPoint(x:1,y:0),CGPoint(x:1,y:1),CGPoint(x:0,y:1)]
    }

    func endPoints() -> [CGPoint] {
        return [CGPoint(x:1,y:1),CGPoint(x:0,y:1),CGPoint.zero,CGPoint(x:1,y:0)]
    }

    func midColorWithFromColor(fromColor:UIColor, toColor:UIColor, progress:CGFloat) -> UIColor {
        var fromR:CGFloat = 0.0,fromG:CGFloat = 0.0,fromB:CGFloat = 0.0,fromAlpha:CGFloat = 0.0
        fromColor.getRed(&fromR,green: &fromG,blue: &fromB,alpha: &fromAlpha)

        var toR:CGFloat = 0.0,toG:CGFloat = 0.0,toB:CGFloat = 0.0,toAlpha:CGFloat = 0.0
        toColor.getRed(&toR,green: &toG,blue: &toB,alpha: &toAlpha)

        let oneR = fromR + (toR - fromR) * progress
        let oneG = fromG + (toG - fromG) * progress
        let oneB = fromB + (toB - fromB) * progress
        let oneAlpha = fromAlpha + (toAlpha - fromAlpha) * progress
        let oneColor = UIColor.init(red: oneR, green: oneG, blue: oneB, alpha: oneAlpha)
        return oneColor
    }

    // This is what you call if you want to draw a full circle.
    func animateCircle(duration: TimeInterval) {
        animateCircleTo(duration: duration, fromValue: 0.010, toValue: 0.99)
    }

    // This is what you call to draw a partial circle.
    func animateCircleTo(duration: TimeInterval, fromValue: CGFloat, toValue: CGFloat){
        // We want to animate the strokeEnd property of the circleLayer
        let animation = CABasicAnimation(keyPath: "strokeEnd")
        animation.isRemovedOnCompletion = true
        // Set the animation duration appropriately
        animation.duration = duration

        // Animate from 0.010 (no circle) to 0.99 (full circle)
        animation.fromValue = 0.010
        animation.toValue = toValue

        // Do an easeout. Don't know how to do a spring instead
        //animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
        animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)

        // Set the circleLayer's strokeEnd property to 0.99 now so that it's the
        // right value when the animation ends.
        let circleMask = self.mask as! CAShapeLayer
        circleMask.strokeEnd = toValue

        // Do the actual animation
        circleMask.removeAllAnimations()
        circleMask.add(animation, forKey: "animateCircle")
    }
}

And this is a little example, how to use in Swift 3.x:

let gradientRingLayer = WCGraintCircleLayer(bounds: CGRect(origin: CGPoint.zero,size:CGSize(width: 150, height: 150)), position:CGPoint(x: 200, y: 300),fromColor:UIColor.blue, toColor:UIColor.white, linewidth:4.0, toValue:0)
self.view.layer.addSublayer(gradientRingLayer)
let duration = 3.0
gradientRingLayer.animateCircleTo(duration: duration, fromValue: 0, toValue: 0.99)

This is the code in Swift 2.x:

import UIKit

class WCGraintCircleLayer: CALayer {

override init () {
    super.init()
}

convenience init(bounds:CGRect,position:CGPoint,fromColor:UIColor,toColor:UIColor,linewidth:CGFloat,toValue:CGFloat) {
    self.init()
    self.bounds = bounds
    self.position = position
    let colors : [UIColor] = self.graintFromColor(fromColor, toColor:toColor, count:4)
    for i in 0..<colors.count-1 {
        let graint = CAGradientLayer()
        graint.bounds = CGRectMake(0,0,CGRectGetWidth(bounds)/2,CGRectGetHeight(bounds)/2)
        let valuePoint = self.positionArrayWithMainBounds(self.bounds)[i]
        graint.position = valuePoint
        print("iesimo graint position: \(graint.position)")
        let fromColor = colors[i]
        let toColor = colors[i+1]
        let colors : [CGColorRef] = [fromColor.CGColor,toColor.CGColor]
        let stopOne: CGFloat = 0.0
        let stopTwo: CGFloat = 1.0
        let locations : [CGFloat] = [stopOne,stopTwo]
        graint.colors = colors
        graint.locations = locations
        graint.startPoint = self.startPoints()[i]
        graint.endPoint = self.endPoints()[i]
        self.addSublayer(graint)
        //Set mask
        let shapelayer = CAShapeLayer()
        let rect = CGRectMake(0,0,CGRectGetWidth(self.bounds) - 2 * linewidth, CGRectGetHeight(self.bounds) - 2 * linewidth)
        shapelayer.bounds = rect
        shapelayer.position = CGPointMake(CGRectGetWidth(self.bounds)/2, CGRectGetHeight(self.bounds)/2)
        shapelayer.strokeColor = UIColor.blueColor().CGColor
        shapelayer.fillColor = UIColor.clearColor().CGColor
        shapelayer.path = UIBezierPath(roundedRect: rect, cornerRadius: CGRectGetWidth(rect)/2).CGPath
        shapelayer.lineWidth = linewidth
        shapelayer.lineCap = kCALineCapRound
        shapelayer.strokeStart = 0.010
        let finalValue = (toValue*0.99)
        shapelayer.strokeEnd = finalValue//0.99;
        self.mask = shapelayer
    }
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

func layerWithWithBounds(bounds:CGRect, position:CGPoint, fromColor:UIColor, toColor:UIColor, linewidth : CGFloat,toValue:CGFloat) -> WCGraintCircleLayer {
    let layer = WCGraintCircleLayer(bounds: bounds,position: position,fromColor:fromColor, toColor: toColor,linewidth: linewidth,toValue:toValue )
    return layer
}

func graintFromColor(fromColor:UIColor, toColor:UIColor, count:Int) -> [UIColor]{
    var fromR:CGFloat = 0.0,fromG:CGFloat = 0.0,fromB:CGFloat = 0.0,fromAlpha:CGFloat = 0.0
    fromColor.getRed(&fromR,green: &fromG,blue: &fromB,alpha: &fromAlpha)

    var toR:CGFloat = 0.0,toG:CGFloat = 0.0,toB:CGFloat = 0.0,toAlpha:CGFloat = 0.0
    toColor.getRed(&toR,green: &toG,blue: &toB,alpha: &toAlpha)

    var result : [UIColor]! = [UIColor]()

    for i in 0...count {
        let oneR:CGFloat = fromR + (toR - fromR)/CGFloat(count) * CGFloat(i)
        let oneG : CGFloat = fromG + (toG - fromG)/CGFloat(count) * CGFloat(i)
        let oneB : CGFloat = fromB + (toB - fromB)/CGFloat(count) * CGFloat(i)
        let oneAlpha : CGFloat = fromAlpha + (toAlpha - fromAlpha)/CGFloat(count) * CGFloat(i)
        let oneColor = UIColor.init(red: oneR, green: oneG, blue: oneB, alpha: oneAlpha)
        result.append(oneColor)
        print(oneColor)

    }
    return result
}

func positionArrayWithMainBounds(bounds:CGRect) -> [CGPoint]{
    let first = CGPointMake((CGRectGetWidth(bounds)/4)*3, (CGRectGetHeight(bounds)/4)*1)
    let second = CGPointMake((CGRectGetWidth(bounds)/4)*3, (CGRectGetHeight(bounds)/4)*3)
    let third = CGPointMake((CGRectGetWidth(bounds)/4)*1, (CGRectGetHeight(bounds)/4)*3)
    let fourth = CGPointMake((CGRectGetWidth(bounds)/4)*1, (CGRectGetHeight(bounds)/4)*1)
    print([first,second,third,fourth])
    return [first,second,third,fourth]
}

func startPoints() -> [CGPoint] {
    return [CGPointMake(0,0),CGPointMake(1,0),CGPointMake(1,1),CGPointMake(0,1)]
}

func endPoints() -> [CGPoint] {
    return [CGPointMake(1,1),CGPointMake(0,1),CGPointMake(0,0),CGPointMake(1,0)]
}

func midColorWithFromColor(fromColor:UIColor, toColor:UIColor, progress:CGFloat) -> UIColor {
    var fromR:CGFloat = 0.0,fromG:CGFloat = 0.0,fromB:CGFloat = 0.0,fromAlpha:CGFloat = 0.0
    fromColor.getRed(&fromR,green: &fromG,blue: &fromB,alpha: &fromAlpha)

    var toR:CGFloat = 0.0,toG:CGFloat = 0.0,toB:CGFloat = 0.0,toAlpha:CGFloat = 0.0
    toColor.getRed(&toR,green: &toG,blue: &toB,alpha: &toAlpha)

    let oneR = fromR + (toR - fromR) * progress
    let oneG = fromG + (toG - fromG) * progress
    let oneB = fromB + (toB - fromB) * progress
    let oneAlpha = fromAlpha + (toAlpha - fromAlpha) * progress
    let oneColor = UIColor.init(red: oneR, green: oneG, blue: oneB, alpha: oneAlpha)
    return oneColor
}

// This is what you call if you want to draw a full circle.
func animateCircle(duration: NSTimeInterval) {
    animateCircleTo(duration, fromValue: 0.010, toValue: 0.99)
}

// This is what you call to draw a partial circle.
func animateCircleTo(duration: NSTimeInterval, fromValue: CGFloat, toValue: CGFloat){
    // We want to animate the strokeEnd property of the circleLayer
    let animation = CABasicAnimation(keyPath: "strokeEnd")
    animation.removedOnCompletion = true
    // Set the animation duration appropriately
    animation.duration = duration

    // Animate from 0.010 (no circle) to 0.99 (full circle)
    animation.fromValue = 0.010
    animation.toValue = toValue

    // Do an easeout. Don't know how to do a spring instead
    //animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
    animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)

    // Set the circleLayer's strokeEnd property to 0.99 now so that it's the
    // right value when the animation ends.
    let circleMask = self.mask as! CAShapeLayer
    circleMask.strokeEnd = toValue

    // Do the actual animation
    circleMask.removeAllAnimations()
    circleMask.addAnimation(animation, forKey: "animateCircle")
}

}

And this is a little example, how to use in Swift 2.x:

let gradientRingLayer = WCGraintCircleLayer(bounds: CGRectMake(0, 0, 150, 150), position:CGPointMake(200,300) ,fromColor:UIColor.blueColor(), toColor:UIColor.whiteColor(),linewidth:4.0, toValue:0)
self.view.layer.addSublayer(gradientRingLayer)
let duration = 3.0
gradientRingLayer.animateCircleTo(duration, fromValue: 0, toValue: 0.99)

This is rapid copy/paste remote pastebin code

static image

Available also with animation:

dynamic image

like image 12
Alessandro Ornano Avatar answered Nov 03 '22 00:11

Alessandro Ornano


I happen to visit this question,and want to post my answer.

The only thing,you need to do is use an CAShapeLayer to set Mask

[graintLayer setMask:shapeLayer]

I wrote an simple library about how to build Circle Graint Layer

This library is here

Here is the screenshot

like image 6
Leo Avatar answered Nov 02 '22 22:11

Leo