LastMove
LastMove

Reputation: 2482

CAKeyFrameAnimation with Color from patternImage

I am trying to animate the backgroundColor of a CALayer with CAKeyFrameAnimation. When I make it with classics colors it works; But with Color generated from patternImage UIColor(patternImage:"imageName").CGColor, it doesn't work at all.

@IBAction func animFirstView(sender: AnyObject)
{
    addAnim(view1, colors: [UIColor.blackColor().CGColor, UIColor.redColor().CGColor]) // THAT WORKS 

}

@IBAction func animSecondView(sender: AnyObject)
{

    var firstColor = UIColor(patternImage: UIImage(named:"stars1")!).CGColor;
    addAnim(view2,
        colors: [firstColor]); // THAT doesn't works at all :(
}

func addAnim(view:UIView, colors:[CGColor])
{
    let anim = CAKeyframeAnimation(keyPath:"backgroundColor")
          anim.values = colors;
    anim.keyTimes = [0.0, 0.25, 0.5, 0.75, 1];
    anim.calculationMode = kCAAnimationDiscrete
    anim.duration = 0.3;
    anim.repeatCount = Float.infinity;
    view.layer.addAnimation(anim, forKey: "backgroundColor");

}

Someone has an idea?

Isn't it possible to do that or am I doing something wrong?

A test case of the "bug" https://github.com/lastMove/patternBugDemo

Upvotes: 2

Views: 901

Answers (1)

matt
matt

Reputation: 535945

I don't know why setting the backgroundColor to a pattern color as part of a keyframe animation doesn't work. I solved this by imitating my own existing example where I set the contents as a keyframe animation:

@IBAction func animSecondView(sender: AnyObject)
{
    var firstColor = UIColor(patternImage: UIImage(named:"stars1")!)
    var secondColor = UIColor(patternImage: UIImage(named:"stars2")!)
    addAnim(view2,
        colors: [firstColor, secondColor, firstColor, secondColor]);
}

func addAnim(view:UIView, colors:[UIColor])
{
    let anim = CAKeyframeAnimation(keyPath:"contents")
    anim.values = colors.map {
        col in
        UIGraphicsBeginImageContextWithOptions(view.bounds.size, true, 0)
        col.setFill()
        UIBezierPath(rect: view.bounds).fill()
        let im = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return im.CGImage
    }
    anim.keyTimes = [0.0, 0.25, 0.75, 1.0];
    anim.calculationMode = kCAAnimationDiscrete
    anim.duration = 1;
    anim.repeatCount = Float.infinity;
    view.layer.addAnimation(anim, forKey: nil);
}

enter image description here

EDIT: Here's another workaround: keep using the layer background color, but change it directly, with a timer:

@IBOutlet weak var view2: UIView!
var colors = [UIColor]()
var timer : NSTimer!
var second = false

@IBAction func animSecondView(sender: AnyObject)
{
    var firstColor = UIColor(patternImage: UIImage(named:"stars1")!)
    var secondColor = UIColor(patternImage: UIImage(named:"stars2")!)
    self.colors = [firstColor, secondColor]
    if let timer = self.timer {
        timer.invalidate()
    }
    self.timer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: "anim:", userInfo: nil, repeats: true)
}
func anim(t:NSTimer) {
    view2.layer.backgroundColor = self.colors[self.second ? 1 : 0].CGColor
    self.second = !self.second
}

Upvotes: 1

Related Questions