How to animate images in CALayer - ios

In my CALayer i am trying to animate images but the animation layer is not showing up. What i am doing wrong in here:
return CALayer().build {
let myLayer = CALayer()
let animation = CAKeyframeAnimation(keyPath: "contents")
animation.fillMode = kCAFillModeForwards
animation.duration = 3
animation.values = TimeLineVC.likeInteractionArray.map {
$0.cgImage as AnyObject
}
animation.repeatCount = 3
myLayer.frame = $0.bounds
myLayer.add(animation, forKey: "contents")
$0.insertSublayer(myLayer, above: $0)
myLayer.backgroundColor = UIColor.black.cgColor
}

It worked for me after adding a few properties:
let animation = CAKeyframeAnimation(keyPath: "contents")
animation.calculationMode = kCAAnimationDiscrete
animation.duration = 3.0
animation.repeatCount = .greatestFiniteMagnitude
animation.autoreverses = false
animation.values = TimeLineVC.likeInteractionArray.map {$0.cgImage!}
animation.isRemovedOnCompletion = false
animation.fillMode = kCAFillModeForwards
animation.beginTime = 0.0
$0.add(animation, forKey: "contents")

Related

CABasicAnimation - Continue animation from Presentation Layer but not as fromValue

I am working on a looping animation that can be cancelled when desired. When the animation is cancelled another animation is called to animate the Presentation Layer back to the fromValue of the previous animation.
The looping animation:
var toBounds = layer.bounds
toBounds.size.height = 12
let animation = CABasicAnimation(keyPath: "bounds")
animation.fromValue = layer.bounds
animation.toValue = toBounds
animation.repeatCount = HUGE
animation.autoreverses = true
animation.duration = 0.3
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
layer.removeAllAnimations()
layer.add(animation, forKey: "oscillation")
The cancel animation:
if let presentationLayer = layer.presentation() {
let animation = CABasicAnimation(keyPath: "bounds")
animation.fromValue = presentationLayer.bounds
animation.toValue = layer.bounds
animation.duration = 0.3
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
layer.removeAllAnimations()
layer.add(animation, forKey: "decay")
}
This makes the animation look smooth when returning to it's original state. However, when the animation gets restarted while the cancel animation is still busy, the animation has this stuttering effect. What I tried to do is change the fromValue in the looping animation but this means that the animation doesn't return to the desired fromValue. How can I make this restart smooth again? Is there a way to set the animation's current value?

Two CABasicAnimations on Two Different Layers Simultaneously

I have a single animation that animates a layer mask successfully:
// create new animation
let anim = CABasicAnimation(keyPath: "path")
anim.delegate = self
anim.fromValue = self.maskLayerMWB.path
anim.toValue = path2.CGPath
anim.duration = 0.2
anim.timingFunction = CAMediaTimingFunction(controlPoints: 0, 1, 1, 1)
self.maskLayerMWB.addAnimation(anim, forKey: nil)
CATransaction.begin()
CATransaction.setDisableActions(true)
self.maskLayerMWB.path = path2.CGPath
CATransaction.commit()
Above works fine. However, right after that, I need to add another CABasicAnimation that gets applied to a different CAShapeLayer.
However, when I add them together as follows, the second animation does not animate, only the first does:
// create new animation
let anim = CABasicAnimation(keyPath: "path")
anim.delegate = self
anim.fromValue = self.maskLayer.path
anim.toValue = path2.CGPath
anim.duration = 0.2
self.maskLayer.addAnimation(anim, forKey: nil)
//Create second Animation
let anim2 = CABasicAnimation(keyPath: "path")
anim2.delegate = self
anim2.fromValue = self.shapeLayer.path
anim2.toValue = path2.CGPath
anim2.duration = 0.2
self.shapeLayer.addAnimation(anim2, forKey: nil)
CATransaction.begin()
CATransaction.setDisableActions(true)
self.maskLayer.path = path2.CGPath
self.shapeLayer.path = path2.CGPath
CATransaction.commit()
I need both animations to happen simultaneously.
I was able to fix this by using CATransaction.setCompletionBlock
CATransaction.begin()
CATransaction.setDisableActions(true)
// create new animation
let anim = CABasicAnimation(keyPath: "path")
anim.delegate = self
anim.fromValue = self.maskLayer.path
anim.toValue = path2.CGPath
anim.duration = 0.2
self.maskLayer.addAnimation(anim, forKey: nil)
//Create second Animation
let anim2 = CABasicAnimation(keyPath: "path")
anim2.delegate = self
anim2.fromValue = self.shapeLayer.path
anim2.toValue = path2.CGPath
anim2.duration = 0.2
self.shapeLayer.addAnimation(anim2, forKey: nil)
CATransaction.setCompletionBlock({
self.maskLayer.path = path2.CGPath
self.shapeLayer.path = path2.CGPath
})
CATransaction.commit()

Animate Gradient View iOS on Linear path using

I am trying to animate a gradient layer continuously. Please see the below gif?
I am using CAGradientLayer, but it only animates on color at a time.
var gradient: CAGradientLayer!
self.gradient = CAGradientLayer()
self.gradient.frame = CGRect(x: 0, y: 0, width:view.layer.frame.size.width, height: 50)
self.gradient.colors = [UIColor.redColor().CGColor, UIColor.redColor().CGColor]
self.view.layer.addSublayer(self.gradient)
self.animateLayer()
func animateLayer () {
let fromColors: NSArray = self.gradient.colors!
let toColors: NSArray = [UIColor.blueColor().CGColor, UIColor.blueColor().CGColor]
self.gradient.colors = toColors as [AnyObject]
let 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")
}

Spinning imageview animation

I want to spin a imageview for forever. I tried following code:
UIView.animateWithDuration(3, animations: {
self.loginLogo.transform = CGAffineTransformMakeRotation((360 * CGFloat(M_PI)) / 360)
}){ (finished) -> Void in
self.rotateImage()
}
But this is working for one time. My imageview is not spinning forever. How can I fix it?
If you want to rotate your image forever you can do it this way:
func rotateViewLayer() {
let rotateView = CABasicAnimation()
rotateView.fromValue = 0.degreesToRadian
rotateView.toValue = 360.degreesToRadian
rotateView.duration = 1
rotateView.repeatCount = Float.infinity
rotateView.removedOnCompletion = false
rotateView.fillMode = kCAFillModeForwards
rotateView.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
imageView.layer.addAnimation(rotateView, forKey: "transform.rotation.z")
}
And here is your helper extension:
extension Int {
var degreesToRadian : CGFloat {
return CGFloat(self) * CGFloat(M_PI) / 180.0
}
}
And you can refer THIS sample project for more Info.
use this on layer of your view
var myImageView:UIImageView?
var rotation = CABasicAnimation(keyPath: "transform.rotation")
rotation.fromValue = 0.0
rotation.toValue = 2*M_PI
rotation.duration = 1.1
rotation.repeatCount = Float.infinity
myImageView?.layer.addAnimation(rotation, forKey: "Spin")
This should work
func startAnimationWithDuration(duration:CGFloat)
{
var rotationAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
rotationAnimation.fromValue = 0
rotationAnimation.toValue = 2 * M_PI
rotationAnimation.duration = NSTimeInterval(duration)
rotationAnimation.repeatCount = 1000.0 //some large value
imageView.layer.addAnimation(rotationAnimation, forKey: "spin")
}

Line animation with constant length along rounded rectangle swift

please, how to do infinity line animation along path (rounded rectangle) without stopping, the line have to have constant/same length in each time - see attached picture
I found out only this solution, but this isn't what I want.
--- for path:
path = UIBezierPath(roundedRect: CGRect.init(x: 0, y: 0, width: 100, height: 100), byRoundingCorners:.allCorners, cornerRadii: CGSize(width:16, height:16))
--- animations:
let strokeEndAnimation: CAAnimation = {
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.fromValue = 0
animation.toValue = 1
animation.duration = 10
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
let group = CAAnimationGroup()
group.duration = 12
group.repeatCount = MAXFLOAT
group.animations = [animation]
return group
}()
let strokeStartAnimation: CAAnimation = {
let animation = CABasicAnimation(keyPath: "strokeStart")
animation.beginTime = 2
animation.fromValue = 0
animation.toValue = 1
animation.duration = 10
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
let group = CAAnimationGroup()
group.duration = 12
group.repeatCount = MAXFLOAT
group.animations = [animation]
return group
}()
Thank You

Resources