Animate Gradient View iOS on Linear path using - ios

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")
}

Related

How to animate images in CALayer

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")

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()

Bezier animation to reveal and conceal a checkmark with Swift

In my app I have a checkmark inside a UIView which I reveal or conceal depending on the button the user clicks on to create the effect that the checkmark is being drawn or erased. I am using Bezier path with a mask to animate the checkmark being revealed or concealed with the code shown below. However, in the code to conceal it, the checkmark is being concealed from right to left and I would like to do it from left to right. What am I missing?
Code to reveal the checkmark
func checkmarkAnimationToReveal(view: UIView) {
let path = UIBezierPath(rect: CGRectMake(0, 0, view.bounds.width / 10, view.bounds.height))
let mask = CAShapeLayer()
mask.anchorPoint = CGPointMake(0.5, 1.0)
mask.path = path.CGPath
view.layer.mask = mask
let anim = CABasicAnimation(keyPath: "path")
anim.fromValue = path.CGPath
anim.toValue = UIBezierPath(rect:view.bounds).CGPath
anim.duration = 1.0
anim.fillMode = kCAFillModeForwards
anim.removedOnCompletion = false
view.layer.mask!.addAnimation(anim, forKey: "anim")
}
Code to conceal the checkmark
func checkmarkAnimationToConceal(view: UIView) {
CATransaction.begin()
CATransaction.setCompletionBlock({
print("completion reached")
self.checkmarkLabel.hidden = true
})
let path = UIBezierPath(rect: CGRectMake(0, 0, view.bounds.width / 10, view.bounds.height))
let mask = CAShapeLayer()
mask.anchorPoint = CGPointMake(0.5, 1.0)
mask.path = path.CGPath
view.layer.mask = mask
let anim = CABasicAnimation(keyPath: "path")
anim.fromValue = UIBezierPath(rect:view.bounds).CGPath
anim.toValue = path.CGPath
anim.duration = 1.0
anim.fillMode = kCAFillModeRemoved
anim.removedOnCompletion = false
view.layer.mask!.addAnimation(anim, forKey: "anim")
}

how to control strokeEnd animation Line Speed

I want to create an atomic motion animation in iOS, but there are some trouble could not solve.
here is my animation result
CAKeyframeAnimation position animation along bezierPath does not match the CABasicAnimation strokeEnd animation(particles animation does not match their wake animation).
2.The wake animation loop is incoherent, CABasicAnimation seems can't represent the Curving segment that strokeStart is positive and strokeEnd is negative.
my code:
let atom = CAShapeLayer()
var rect = CGRect(x: 0,y: 0,width: 5,height: 5)
var path = UIBezierPath(roundedRect: rect,cornerRadius: 5.0)
atom.path = path.CGPath;
atom.strokeColor = UIColor.greenColor().CGColor
atom.bounds = rect;
rect = CGRect(x: 0,y: 0,width: 300,height: 50);
path = UIBezierPath(ovalInRect:rect);
let orbit = CAShapeLayer()
orbit.path = path.CGPath;
orbit.strokeColor = UIColor.whiteColor().CGColor
orbit.lineWidth = 1;
orbit.fillColor = UIColor.clearColor().CGColor
orbit.bounds = CGPathGetPathBoundingBox(path.CGPath);
orbit.position = CGPoint(x:150,y:25)
rect = CGRect(x: 0,y: 0,width: 300,height: 50);
path = UIBezierPath(ovalInRect:rect);
let keyani = CAKeyframeAnimation(keyPath: "position");
keyani.path = path.CGPath
keyani.duration = 3.0;
keyani.repeatCount = HUGE;
keyani.additive = true
keyani.calculationMode = kCAAnimationPaced
keyani.rotationMode = kCAAnimationRotateAuto
keyani.timingFunction = CAMediaTimingFunction(name:kCAMediaTimingFunctionLinear);
atom.addAnimation(keyani, forKey: "")
let orbitAni = CABasicAnimation(keyPath: "strokeStart")
orbitAni.byValue = 1.0
orbitAni.cumulative = true
let orbitAni1 = CABasicAnimation(keyPath: "strokeEnd")
orbitAni1.fromValue = 0.0
orbitAni1.toValue = 1.0
let animationGroup = CAAnimationGroup()
animationGroup.animations = [orbitAni,orbitAni1]
animationGroup.duration = 3.0
animationGroup.repeatCount = HUGE
orbit.strokeStart = -0.2
orbit.addAnimation(animationGroup, forKey: "");
orbit.shadowRadius = 5.0;
orbit.shadowColor = UIColor.greenColor().CGColor
orbit.shadowOpacity = 0.5
orbit.shadowOffset = CGSizeZero
var trans = CGAffineTransformIdentity
trans = CGAffineTransformRotate(trans, CGFloat(M_PI_4))
repeator.instanceTransform = CATransform3DMakeAffineTransform (trans)
repeator.instanceCount = 4;
repeator.instanceDelay = 0;
repeator.addSublayer(orbit)
repeator.addSublayer(atom)
repeator.bounds = CGRect(x: 0,y: 0,width: 300,height: 50)
repeator.position = CGPoint(x:200,y:200)
repeator.anchorPoint = CGPoint(x:0.5,y:0.5)
repeator.instanceAlphaOffset = 1.0

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