First, I will introduce the agent method of CAAnimation. CAAnimationDelegate has two alternative proxy methods:
func animationDidStart(_ anim: CAAnimation) func animationDidStop(_ anim: CAAnimation, finished flag: Bool)
Cabasic animation inherits to CAAnimation. They are all written in Objective-C, and they follow the key value coding style, which means that you can use them as dictionaries and add new properties to them at run time.
We continue to use the cabasic animation object flyRight that we created earlier. For example:
flyRight.setValue("form", forKey: "name")
Now you can judge whether it is a copy of the current animation according to name in its proxy method. You can also assign a username.layer to it to keep references to a layer. for example
flyRight.setValue(username.layer, forKey: "layer") flyRight.setValue(password.layer, forKey: "layer")
The whole code is as follows:
let flyRight = CABasicAnimation(keyPath: "position.x") flyRight.fromValue = -view.bounds.size.width/2 flyRight.toValue = view.bounds.size.width/2 flyRight.duration = 0.5 flyRight.delegate = self flyRight.setValue("form", forKey: "name") flyRight.setValue(heading.layer, forKey: "layer") heading.layer.add(flyRight, forKey: nil)//Copy a copy of flyRight to heading.layer flyRight.beginTime = CACurrentMediaTime() + 0.3 flyRight.fillMode = kCAFillModeBoth flyRight.setValue(username.layer, forKey: "layer") username.layer.add(flyRight, forKey: nil)//Copy a copy of flyRight to username.layer flyRight.beginTime = CACurrentMediaTime() + 0.4 flyRight.setValue(password.layer, forKey: "layer") password.layer.add(flyRight, forKey: nil)//Copy a copy of flyRight to password.layer
Proxy method implementation:
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { print("animation did finish") guard let name = anim.value(forKey: "name") as? String else { return } if name == "form" { //form field found let layer = anim.value(forKey: "layer") as? CALayer anim.setValue(nil, forKey: "layer")//Remove reference to layer when animation is complete let pulse = CABasicAnimation(keyPath: "transform.scale")//Start a new animation pulse.fromValue = 1.25 pulse.toValue = 1.0 pulse.duration = 0.25 layer?.add(pulse, forKey: nil) } }
Example: add two animations to the label named info
let flyLeft = CABasicAnimation(keyPath: "position.x") flyLeft.fromValue = info.layer.position.x + view.frame.size.width flyLeft.toValue = info.layer.position.x flyLeft.duration = 5.0 info.layer.add(flyLeft, forKey: "infoappear") let fadeLabelIn = CABasicAnimation(keyPath: "opacity") fadeLabelIn.fromValue = 0.2 fadeLabelIn.toValue = 1.0 fadeLabelIn.duration = 4.5 info.layer.add(fadeLabelIn, forKey: "fadein")
Two other methods are introduced
- info.layer.animationKeys(): we can get the key values of all animation s of the layer
- info.layer.removeAnimation(forKey: "infoapp ear"): remove the animation whose key is infoapp ear under the layer
If you want to perform multiple animations simultaneously on a single layer, you can also use CAAnimationGroup, which will be described later.