I'm currently trying to implement a circle with an animated stroke - which works fine (see image below).
For a while now, I've been trying to add a gradient to the circle's stroke. I'm am using a piece of code I already have used to underline a UITextField
.
How can I apply my code for the gradient to the shapeLayer
's stroke?
Circle:
let color = UIColor(red: 11/255, green: 95/255, blue: 244/255, alpha: 1)
let trackLayer = CAShapeLayer()
let center = CGPoint(x: circleView.frame.size.width/2, y: circleView.frame.size.height / 1.3)
let circularPath = UIBezierPath(arcCenter: center, radius: 120, startAngle: CGFloat.pi, endAngle: 2 * CGFloat.pi, clockwise: true)
trackLayer.path = circularPath.cgPath
trackLayer.strokeColor = UIColor.groupTableViewBackground.cgColor
trackLayer.lineWidth = 14
trackLayer.fillColor = UIColor.clear.cgColor
shapeLayer.path = circularPath.cgPath
shapeLayer.strokeColor = color.cgColor
shapeLayer.lineWidth = 15
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.strokeEnd = 0
circleView.layer.addSublayer(trackLayer)
circleView.layer.addSublayer(shapeLayer)
Code Gradient:
let color = UIColor(red: 11/255, green: 95/255, blue: 244/255, alpha: 1).cgColor
let sndColor = UIColor(red: 124/255, green: 206/255, blue: 254/255, alpha: 1).cgColor
let gradient: CAGradientLayer = CAGradientLayer()
gradient.colors = [color, sndColor]
gradient.locations = [0.0, 0.8]
gradient.startPoint = CGPoint(x: 0, y: 0)
gradient.endPoint = CGPoint(x: 1, y: 0)
let width = CGFloat(3.0)
gradient.frame = CGRect(x: 0, y: self.frame.size.height - width, width: self.frame.size.width, height: self.frame.size.height)
self.layer.insertSublayer(gradient, at: 0)
self.layer.masksToBounds = true
Edit:
My stroke animation:
func animateStroke() {
if !animated {
animated = true
let basicAnimation = CABasicAnimation(keyPath: "strokeEnd")
var value: Double?
if expectedCosts <= monthlyPrice {
value = 1
} else {
value = monthlyPrice / expectedCosts
}
basicAnimation.toValue = value
basicAnimation.duration = 1.5
basicAnimation.fillMode = CAMediaTimingFillMode.forwards
basicAnimation.isRemovedOnCompletion = false
basicAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
shapeLayer.add(basicAnimation, forKey: "strokeAnimation")
}
}
Stroke code:
func displayCircle() {
let color = UIColor(red: 11/255, green: 95/255, blue: 244/255, alpha: 1)
let trackLayer = CAShapeLayer()
let center = CGPoint(x: circleView.frame.size.width/2, y: circleView.frame.size.height / 1.3)
let circularPath = UIBezierPath(arcCenter: center, radius: 120, startAngle: CGFloat.pi, endAngle: 2 * CGFloat.pi, clockwise: true)
trackLayer.path = circularPath.cgPath
trackLayer.strokeColor = UIColor.groupTableViewBackground.cgColor
trackLayer.lineWidth = 14
trackLayer.fillColor = UIColor.clear.cgColor
shapeLayer.path = circularPath.cgPath
shapeLayer.strokeColor = color.cgColor
shapeLayer.lineWidth = 15
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.strokeEnd = 0
circleView.layer.addSublayer(trackLayer)
circleView.layer.addSublayer(shapeLayer)
let sndColor = UIColor(red: 124/255, green: 206/255, blue: 254/255, alpha: 1).cgColor
let gradient: CAGradientLayer = CAGradientLayer()
gradient.colors = [color, sndColor]
gradient.locations = [0.0, 0.8]
gradient.startPoint = CGPoint(x: 0, y: 0)
gradient.endPoint = CGPoint(x: 1, y: 0)
gradient.frame = circleView.bounds
gradient.mask = trackLayer
circleView.layer.addSublayer(gradient)
}