layer动画的实现
layer动画就是层动画,工作原理和视图动画相同。在开始或者是结束时间改变la ye r的属性值,layer相对于视图有很多的可动画属性。因此layer可以提供相对多的动画属性选择
一下为仿照登录界面进行的layer动画
为label 标题添加动画,让它从屏幕的外部动画到屏幕的中央位置
*CABasicAnimation描述的是一个未知层的动画,可以使用于所有的层,每一层就相当于运行一次它的动画copy。用keyPath来指明动画的属性,position相当于当前的层相对于父层的位置 *
let flyRight = CABasicAnimation(keyPath: "position.x") flyRight.fillMode = kCAFillModeBoth//在动画开始和结束的时候控制动画的行为 flyRight.fromValue = -view.bounds.size.width / 2 flyRight.toValue = view.bounds.size.width / 2 flyRight.duration = 0.5 heading.layer.addAnimation(flyRight, forKey: nil)//为heading层增加一个layer动画
注意点:fillMode默认为re moved,动画开始就是设置的begin time 。若是没有,标示动画立即执行。动画结束,layer从屏幕中移除;backwords属性,会在屏幕上显示动画第一帧,知道动画开始;forwords属性,标示动画结束后,会一直保留layer对象;bouth属性混合了backwords和forwords的特点
在这个基础上为用户的用户名的textfield添加一个layer动画
注意点:由于CABasicAnimation只是一个数据模型,没有绑定任何一个层。addAnimation会讲动画添加到层上面
代码如下:
flyRight.beginTime = CACurrentMediaTime() + 0.3//begintime属性设置了动画的绝对时间,相对增加0.3s的延迟 username.layer.addAnimation(flyRight, forKey: nil)
如何处理layer在结束的时候不在指定位置的情况
补充知识点:通过debug调试代码
debug调试1.png debug调试2.png debug调试3.png通过调试,可以清楚地看到控件最终的位置
点击登录按钮用layer改编背景颜色
func tintBackgroundColor(layer layer: CALayer, toColor: UIColor) { let tint = CABasicAnimation(keyPath: "backgroundColor") tint.fromValue = layer.backgroundColor tint.toValue = toColor.CGColor tint.duration = 1.0 layer.addAnimation(tint, forKey: nil) layer.backgroundColor = toColor.CGColor }
效果图:
layer动画.gif动画的键和委托的实现
在之前做视图动画的时候,是不能够暂停,停止,访问动画的。layer动画可以实现对动画的访问,并且可以在动画上建立一个委托对象来访问动画事件。和uikit动画相比,la ye r可以在动画开始,结束,或者在动画的执行过程中,通过动画委托代理做出相应的操作。那么,la ye r的怎样理解layer的委托协议,怎样在委托协议中检测和控制layer动画,键值配对?
动画委托
CAAnimation以及它的子类CABasicAnimation是实现委托的,因此我们可以直接相应动画的实现。CAAnimation并没有特定的协议来实现动画的委托,而是在CAAnimation的声明文件中,对nsobjec进行扩展,增加了动画开始和结束2个扩展方法。
用代理实现一个业务:layer动画到达最终的位置后显示控制台相关信息
- 实现完成代理方法标示动画思路: layer动画都是满足键值配对的,类似于字典,当创建好一个属性后对它进行跟踪。所以,为动画模型分配一个name作为标示。对每次动画控件的layer进行一次层的引用。
func animationDidStop(anim: CAAnimation, finished flag: Bool) { if let name = anim.valueForKey("name") as? String{ //将可变类型转换成字符串 if name == "form" { let layer = anim.valueForKey("layer") as? CALayer//转变成calayer的可选类型,也可能转变失败。 anim.setValue(nil, forKey: "layer")//当layer==nil时,应该移除动画执行的layer。然后创建一个全新的动画(使layer从1.25倍缩小到1倍) let pulse = CABasicAnimation (keyPath: "transform.scale") pulse.fromValue = 1.25 pulse.toValue = 1.0 pulse.duration = 0.25 layer?.addAnimation(pulse, forKey: nil)//layer为nil的话将不会添加动画 } } }
实现一个功能业务,在控制台上显示一个动画label,label逐渐显现。当点击任意个textfield时,label显示到最终的位置上
核心代码:
//label从右向左滑动的效果 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.addAnimation(flyLeft, forKey: "infoappear")//info动画的标示 //label淡入淡出的效果 let fadeLabelIn = CABasicAnimation(keyPath: "opacity") fadeLabelIn.fromValue = 0.2 fadeLabelIn.toValue = 1.0 fadeLabelIn.duration = 4.5 info.layer.addAnimation(fadeLabelIn, forKey: "fadein”)
点击textfield时,让动画进行停止平移
extension ViewController : UITextFieldDelegate { func textFieldDidBeginEditing(textField: UITextField) { print(info.layer.animationKeys()) info.layer.removeAnimationForKey("infoappear")//移除平移的动画 } }
设置云朵动画的思路:为每一个云朵添加layer动画,动画结束之后需要重新为云朵添加动画
每一个云朵添加layer动画代码:
func animateCloud(layer: CALayer) { //1 let cloudSpeed = 60.0 / Double(view.layer.frame.size.width) let duration: NSTimeInterval = Double(view.layer.frame.size.width - layer.frame.origin.x) * cloudSpeed //2 let cloudMove = CABasicAnimation(keyPath: "position.x") cloudMove.duration = duration cloudMove.toValue = self.view.bounds.size.width + layer.bounds.width/2 cloudMove.delegate = self cloudMove.setValue("cloud", forKey: "name") cloudMove.setValue(layer, forKey: "layer") layer.addAnimation(cloudMove, forKey: nil) }
//重置layer动画代码:
if name == "cloud" { if let layer = anim.valueForKey("layer") as? CALayer { anim.setValue(nil, forKey: "layer") layer.position.x = -layer.bounds.width/2 delay(seconds: 0.5, completion: { self.animateCloud(layer) }) } }
运行效果:
layer委托效果图.gif
网友评论