Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animate CAGradientLayer in Swift

I am attemping to animate the CAGradientLayer using Swift. For a resource I'm using this post

Here is my code

class ViewController: UIViewController {

  var gradient : CAGradientLayer?;

  override func viewDidLoad() {
    super.viewDidLoad()
  }

  override func viewDidAppear(animated: Bool) {

    self.gradient = CAGradientLayer()
    self.gradient?.frame = self.view.bounds
    self.gradient?.colors = [ UIColor.redColor().CGColor, UIColor.redColor().CGColor]
    self.view.layer.insertSublayer(self.gradient, atIndex: 0)

    animateLayer()
  }

  func animateLayer(){

    var fromColors = self.gradient?.colors
    var toColors: [AnyObject] = [ UIColor.blueColor().CGColor, UIColor.blueColor().CGColor]

    var animation : CABasicAnimation = CABasicAnimation(keyPath: "colors")

    animation.fromValue = fromColors
    animation.toValue = toColors
    animation.duration = 3.00
    animation.removedOnCompletion = true
    animation.fillMode = kCAFillModeForwards
    animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
    animation.delegate = self

    self.gradient?.addAnimation(animation, forKey:"animateGradient")
  }
}

I've attempted this in Objective-C and it works, but I need to use it in Swift and when I run the program it animates but goes back to the previous color at the end, I need it so remain blue.

like image 848
DrPatience Avatar asked Jul 22 '15 09:07

DrPatience


3 Answers

I have checked your code and found one mistake here. You forgot to set color of self.gradient you are just giving colors to animation thats why animation is working fine and at the end you see its color goes back to red.

Write this missing code:

var toColors: [AnyObject] = [UIColor.blueColor().CGColor, UIColor.blueColor().CGColor]
self.gradient.colors = toColors // You missed this line
var animation : CABasicAnimation = CABasicAnimation(keyPath: "colors")

You can also check working code here: Sample

UPDATE: how do I repeat this gradient transition continuously ?

So you can use delegate of CAAnimation. It will let you know once the animation has been finished and then you can set the fromColors and toColors value and call the animateLayer() function again and again. But for this you will have to make few changes in your code.

  • Make fromColors and toColors global.
  • Change their value in animationDidStop delegate method.
  • Call the animateLayer() function again.

Here is the delegate method body:

override func animationDidStop(anim: CAAnimation!, finished flag: Bool) {

    self.toColors = self.fromColors;
    self.fromColors = self.gradient?.colors
    animateLayer()
}

And you can also check working code here: Sample

like image 92
TheTiger Avatar answered Nov 05 '22 08:11

TheTiger


For those in the comments asking about endless animations, here's my stock sample code for an endlessly animated background:-

The full discussion and results can be seen on my blog

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // create the gradient layer
        let gradient = CAGradientLayer()
        gradient.frame = self.view.bounds
        gradient.startPoint = CGPoint(x:0.0, y:0.5)
        gradient.endPoint = CGPoint(x:1.0, y:0.5)
        gradient.colors = [UIColor.red.cgColor, UIColor.green.cgColor]
        gradient.locations =  [-0.5, 1.5]

        let animation = CABasicAnimation(keyPath: "colors")
        animation.fromValue = [UIColor.red.cgColor, UIColor.green.cgColor]
        animation.toValue = [UIColor.green.cgColor, UIColor.red.cgColor]
        animation.duration = 5.0
        animation.autoreverses = true
        animation.repeatCount = Float.infinity

        // add the animation to the gradient
        gradient.add(animation, forKey: nil)

        // add the gradient to the view
        self.view.layer.addSublayer(gradient)
    }
 }
like image 6
Echelon Avatar answered Nov 05 '22 08:11

Echelon


For future reference... The 100% CPU usage is caused by the animationDidStop function. It restarts the animation while the current animations isn't finished. Please check the finished flag:

override func animationDidStop(anim: CAAnimation, finished: Bool) {
    if finished {
        self.toColors = self.fromColors;
        self.fromColors = self.gradient?.colors

        animateLayer()
    }
}
like image 1
user2152001 Avatar answered Nov 05 '22 06:11

user2152001