Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/105.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 圆形梯度_Ios_Swift - Fatal编程技术网

Ios 圆形梯度

Ios 圆形梯度,ios,swift,Ios,Swift,我试图画一个圆形的渐变 let backgroundView:UIView = UIView() let backgroundLayer:CAShapeLayer = CAShapeLayer() let gradient:CAGradientLayer = CAGradientLayer() ... backgroundLayer.frame = CGRectMake(0, 0, backgroundDiameter, backgroundDiameter) backgroundLayer.

我试图画一个圆形的渐变

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)
但是,坡度似乎不受以下因素的影响:

backgroundLayer.path = CGPathCreateWithEllipseInRect(backgroundLayer.frame, nil)
并且仍然有它最初的形状。 有没有一种方法可以在不使用CGContext*指令的情况下,使用椭圆形状的图层来遮罩渐变

谢谢,


MG

如果背景层只是作为渐变层的遮罩,请使用

gradient.mask = backgroundLayer
并将渐变添加到视图的层中

backgroundView.layer.addSublayer(gradient)

否则,创建一个新的
CAShapeLayer
作为渐变的maskLayer

我碰巧访问了这个问题,想发布我的答案

唯一需要做的就是使用CAShapeLayer设置遮罩

[graintLayer setMask:shapeLayer]
我写了一个关于如何构建圆形颗粒层的简单库

这是截图

我已经翻译成了Swift 3.x,换句话说,好的WCGradientCircleLayer是用objective-C编写的(它的工作原理与aspected完全相同)

这是Swift2.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")
}
这是远程快速复制/粘贴

也可用于动画

此处转换为Swift 3。感谢亚历山德罗·奥纳诺的Swift 2.3翻译

代码:


我发现了一个更简单的答案,没有使用多层,混合多层可能会影响动画性能,通常应该尽量避免

override func draw(_ rect: CGRect) {
    let lineWidth: CGFloat = CGFloat(2)
    let strokeColor: UIColor = UIColor.black
    let startAngle: CGFloat = 0
    let maxAngle: CGFloat = CGFloat(Double.pi * 2)
    let lineCapStyle: CGLineCap = .round

    let gradations = 255
    let center = CGPoint(x: bounds.origin.x + bounds.size.width / 2, y: bounds.origin.y + bounds.size.height / 2)
    let radius = (min(bounds.size.width, bounds.size.height) - lineWidth) / 2

    for i in 1 ... gradations {
        let percent0 = CGFloat(i - 1) / CGFloat(gradations)
        let percent1 = CGFloat(i) / CGFloat(gradations)
        let angle0 = startAngle + (maxAngle - startAngle) * percent0
        let angle1 = startAngle + (maxAngle - startAngle) * percent1

        let context = UIGraphicsGetCurrentContext()!
        context.setLineWidth(lineWidth)
        context.setLineCap(lineCapStyle)

        let path = CGMutablePath()
        path.addArc(center: center, radius: radius + lineWidth / 2, startAngle: angle0, endAngle: angle1, clockwise: true)
        path.addArc(center: center, radius: radius - lineWidth / 2, startAngle: angle1, endAngle: angle0, clockwise: false)
        path.closeSubpath()

        let colors = [strokeColor.withAlphaComponent(percent0).cgColor, strokeColor.withAlphaComponent(percent1).cgColor]
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        let colorLocations: [CGFloat] = [0.0, 1.0]
        let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: colorLocations)!
        let startPoint = CGPoint.init(x: center.x + cos(angle0) * radius, y: center.y + sin(angle0) * radius)
        let endPoint = CGPoint.init(x: center.x + cos(angle1) * radius, y: center.y + sin(angle1) * radius)

        context.saveGState()
        context.addPath(path)
        context.clip()
        context.drawLinearGradient(gradient, start: startPoint, end: endPoint, options: [])
        context.restoreGState()
    }
}

从iOS 12开始,您可以使用kCAGradientLayerConic作为渐变层的类型:

// Conical gradient layer
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = self.clockView.bounds;
gradientLayer.type = kCAGradientLayerConic;
gradientLayer.startPoint = CGPointMake(0.5, 0.5);
gradientLayer.endPoint = CGPointMake(1, 1.0);
gradientLayer.colors = @[(__bridge id)[UIColor colorWithRed:1.0/255.0 green:25.0/255.0 blue:147.0/255.0 alpha:1.0].CGColor,
(__bridge id)[UIColor colorWithRed:250.0/255.0 green:226.0/255.0 blue:50.0/255.0 alpha:1.0].CGColor,
(__bridge id)[UIColor colorWithRed:250.0/255.0 green:226.0/255.0 blue:50.0/255.0 alpha:1.0].CGColor,
(__bridge id)[UIColor colorWithRed:1.0/255.0 green:25.0/255.0 blue:147.0/255.0 alpha:1.0].CGColor];
gradientLayer.locations = @[[NSNumber numberWithFloat:0.0f], [NSNumber numberWithFloat:0.4], [NSNumber numberWithFloat:0.5], [NSNumber numberWithFloat:0.6], [NSNumber numberWithFloat:1.0f]];

// Circular mask for gradient layer
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = gradientLayer.bounds;
CGMutablePathRef circlePath = CGPathCreateMutable();
CGPathAddEllipseInRect(circlePath, NULL, CGRectInset(self.view.layer.bounds, 10.0, 10.0));
maskLayer.path = circlePath;
gradientLayer.mask = maskLayer;
[self.view.layer addSublayer:gradientLayer];
CGPathRelease(circlePath);

// Place a second layer over the gradient layer...
CALayer *circleLayer = [CALayer layer];
circleLayer.frame = gradientLayer.bounds;
[circleLayer setBackgroundColor:[UIColor darkGrayColor].CGColor];

// ...and mask it with a smaller circle                                         
CAShapeLayer *maskLayer2 = [CAShapeLayer layer];
maskLayer2.frame = circleLayer.bounds;
CGMutablePathRef circlePath2 = CGPathCreateMutable();
CGPathAddEllipseInRect(circlePath2, NULL, CGRectInset(self.view.layer.bounds, 60.0, 60.0));

maskLayer2.path = circlePath2;
CGPathRelease(circlePath2);
circleLayer.mask = maskLayer2;
[self.view.layer insertSublayer:circleLayer atIndex:1];

有没有这样的吊舱?现在终于在现代iOS中变得微不足道了
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)
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")
  }

}
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)
override func draw(_ rect: CGRect) {
    let lineWidth: CGFloat = CGFloat(2)
    let strokeColor: UIColor = UIColor.black
    let startAngle: CGFloat = 0
    let maxAngle: CGFloat = CGFloat(Double.pi * 2)
    let lineCapStyle: CGLineCap = .round

    let gradations = 255
    let center = CGPoint(x: bounds.origin.x + bounds.size.width / 2, y: bounds.origin.y + bounds.size.height / 2)
    let radius = (min(bounds.size.width, bounds.size.height) - lineWidth) / 2

    for i in 1 ... gradations {
        let percent0 = CGFloat(i - 1) / CGFloat(gradations)
        let percent1 = CGFloat(i) / CGFloat(gradations)
        let angle0 = startAngle + (maxAngle - startAngle) * percent0
        let angle1 = startAngle + (maxAngle - startAngle) * percent1

        let context = UIGraphicsGetCurrentContext()!
        context.setLineWidth(lineWidth)
        context.setLineCap(lineCapStyle)

        let path = CGMutablePath()
        path.addArc(center: center, radius: radius + lineWidth / 2, startAngle: angle0, endAngle: angle1, clockwise: true)
        path.addArc(center: center, radius: radius - lineWidth / 2, startAngle: angle1, endAngle: angle0, clockwise: false)
        path.closeSubpath()

        let colors = [strokeColor.withAlphaComponent(percent0).cgColor, strokeColor.withAlphaComponent(percent1).cgColor]
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        let colorLocations: [CGFloat] = [0.0, 1.0]
        let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: colorLocations)!
        let startPoint = CGPoint.init(x: center.x + cos(angle0) * radius, y: center.y + sin(angle0) * radius)
        let endPoint = CGPoint.init(x: center.x + cos(angle1) * radius, y: center.y + sin(angle1) * radius)

        context.saveGState()
        context.addPath(path)
        context.clip()
        context.drawLinearGradient(gradient, start: startPoint, end: endPoint, options: [])
        context.restoreGState()
    }
}
// Conical gradient layer
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = self.clockView.bounds;
gradientLayer.type = kCAGradientLayerConic;
gradientLayer.startPoint = CGPointMake(0.5, 0.5);
gradientLayer.endPoint = CGPointMake(1, 1.0);
gradientLayer.colors = @[(__bridge id)[UIColor colorWithRed:1.0/255.0 green:25.0/255.0 blue:147.0/255.0 alpha:1.0].CGColor,
(__bridge id)[UIColor colorWithRed:250.0/255.0 green:226.0/255.0 blue:50.0/255.0 alpha:1.0].CGColor,
(__bridge id)[UIColor colorWithRed:250.0/255.0 green:226.0/255.0 blue:50.0/255.0 alpha:1.0].CGColor,
(__bridge id)[UIColor colorWithRed:1.0/255.0 green:25.0/255.0 blue:147.0/255.0 alpha:1.0].CGColor];
gradientLayer.locations = @[[NSNumber numberWithFloat:0.0f], [NSNumber numberWithFloat:0.4], [NSNumber numberWithFloat:0.5], [NSNumber numberWithFloat:0.6], [NSNumber numberWithFloat:1.0f]];

// Circular mask for gradient layer
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = gradientLayer.bounds;
CGMutablePathRef circlePath = CGPathCreateMutable();
CGPathAddEllipseInRect(circlePath, NULL, CGRectInset(self.view.layer.bounds, 10.0, 10.0));
maskLayer.path = circlePath;
gradientLayer.mask = maskLayer;
[self.view.layer addSublayer:gradientLayer];
CGPathRelease(circlePath);

// Place a second layer over the gradient layer...
CALayer *circleLayer = [CALayer layer];
circleLayer.frame = gradientLayer.bounds;
[circleLayer setBackgroundColor:[UIColor darkGrayColor].CGColor];

// ...and mask it with a smaller circle                                         
CAShapeLayer *maskLayer2 = [CAShapeLayer layer];
maskLayer2.frame = circleLayer.bounds;
CGMutablePathRef circlePath2 = CGPathCreateMutable();
CGPathAddEllipseInRect(circlePath2, NULL, CGRectInset(self.view.layer.bounds, 60.0, 60.0));

maskLayer2.path = circlePath2;
CGPathRelease(circlePath2);
circleLayer.mask = maskLayer2;
[self.view.layer insertSublayer:circleLayer atIndex:1];