CALayer层动画详解(一)
2018-04-28 本文已影响35709人
z小志
1、UIView和CALayer的区别
UIView
集成UIResponder,可以响应事件;
负责对内容的管理;
位置属性只有frame、bounds、center
CALayer
只负责内容的创建,绘制
位置属性只有frame、bounds、center、anchorPoint、position
2、Core Animation 核心动画的特点以及各种动画类的继承关系
Core Animation来自iOS的QuartzCore.Framework 框架,它具备以下特点:
1、直接作用于CALayer,而非UIView;
2、Core Animation执行过程在后台执行,不阻塞主线程
3、可以利用CALayer绝大多数属性制作高级动画效果
CAAnimation是所有动画对象的父类,负责控制动画的持续时间和速度,是个抽象类,不能直接使用,应该使用它具体的子类
属性解析:(红色代表来自CAMediaTiming协议的属性)
duration:动画的持续时间
repeatCount:动画的重复次数
repeatDuration:动画的重复时间
removedOnCompletion:默认为YES,代表动画执行完毕后就从图层上移除,图形会恢复到动画执行前的状态。如果想让图层保持显示动画执行后的状态,那就设置为NO,不过还要设置fillMode为kCAFillModeForwards
fillMode:决定当前对象在非active时间段的行为.比如动画开始之前,动画结束之后
beginTime:可以用来设置动画延迟执行时间,若想延迟2s,就设置为CACurrentMediaTime()+2,CACurrentMediaTime()为图层的当前时间
timingFunction:速度控制函数,控制动画运行的节奏
delegate:动画代理
CAPropertyAnimation是CAAnimation的子类,也是个抽象类,要想创建动画对象,应该使用它的两个子类:CABasicAnimation和CAKeyframeAnimation
属性解析:
keyPath:通过指定CALayer的一个属性名称为keyPath(NSString类型),并且对CALayer的这个属性的值进行修改,达到相应的动画效果。比如,指定@”position”为keyPath,就修改CALayer的position属性的值,以达到平移的动画效果
CABasicAnimation是CAPropertyAnimation的子类
属性解析:
fromValue:keyPath相应属性的初始值
toValue:keyPath相应属性的结束值
随着动画的进行,在长度为duration的持续时间内,keyPath相应属性的值从fromValue渐渐地变为toValue
如果fillMode=kCAFillModeForwards和removedOnComletion=NO,那么在动画执行完毕后,图层会保持显示动画执行后的状态。但在实质上,图层的属性值还是动画执行前的初始值,并没有真正被改变。比如,CALayer的position初始值为(0,0),CABasicAnimation的fromValue为(10,10),toValue为(100,100),虽然动画执行完毕后图层保持在(100,100)这个位置,实质上图层的position还是为(0,0)
CAKeyframeAnimation是CApropertyAnimation的子类,跟CABasicAnimation的区别是:CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue),而CAKeyframeAnimation会使用一个NSArray保存这些数值
属性解析:
values:就是上述的NSArray对象。里面的元素称为”关键帧”(keyframe)。动画对象会在指定的时间(duration)内,依次显示values数组中的每一个关键帧
path:可以设置一个CGPathRef\CGMutablePathRef,让层跟着路径移动。path只对CALayer的anchorPoint和position起作用。如果你设置了path,那么values将被忽略
keyTimes:可以为对应的关键帧指定对应的时间点,其取值范围为0到1.0,keyTimes中的每一个时间值都对应values中的每一帧.当keyTimes没有设置的时候,各个关键帧的时间是平分的
CABasicAnimation可看做是最多只有2个关键帧的CAKeyframeAnimation
CAAnimationGroup
CAAnimation的子类,可以保存一组动画对象,将CAAnimationGroup对象加入层后,组中所有动画对象可以同时并发运行
属性解析:
animations:用来保存一组动画对象的NSArray
默认情况下,一组动画对象是同时运行的,也可以通过设置动画对象的beginTime属性来更改动画的开始时间
CATransition是CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。iOS比Mac OS X的转场动画效果少一点
UINavigationController就是通过CATransition实现了将控制器的视图推入屏幕的动画效果
属性解析:
type:动画过渡类型
subtype:动画过渡方向
startProgress:动画起点(在整体动画的百分比)
endProgress:动画终点(在整体动画的百分比)
2、CALayer动画合集
//位置
func positionAnimation(){
let animation = CABasicAnimation()
animation.keyPath = "position"
animation.toValue = CGPoint(x: b_btn.x - 10, y: b_btn.y - 10)
animation.duration = 2
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
b_btn.layer.add(animation, forKey: nil)
}
注:fillMode的作用就是决定当前对象过了非active时间段的行为. 比如动画开始之前,动画结束之后。如果是一个动画CAAnimation,则需要将其removedOnCompletion设置为NO,要不然fillMode不起作用.
下面来讲各个fillMode的意义
kCAFillModeRemoved 这个是默认值,也就是说当动画开始前和动画结束后,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态
kCAFillModeForwards 当动画结束后,layer会一直保持着动画最后的状态
kCAFillModeBackwards 这个和kCAFillModeForwards是相对的,就是在动画开始前,你只要将动画加入了一个layer,layer便立即进入动画的初始状态并等待动画开始.你可以这样设定测试代码,将一个动画加入一个layer的时候延迟5秒执行.然后就会发现在动画没有开始的时候,只要动画被加入了layer,layer便处于动画初始状态
kCAFillModeBoth 理解了上面两个,这个就很好理解了,这个其实就是上面两个的合成.动画加入后开始之前,layer便处于动画初始状态,动画结束后layer保持动画最后的状态.
//缩放
func transformScaleAnimation(){
let animation = CABasicAnimation()
animation.keyPath = "transform.scale.x"
animation.fromValue = 1.0
animation.toValue = 0.8
animation.duration = 2
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
b_btn.layer.add(animation, forKey: nil)
}
//旋转
func transformRotationAnimation(){
let animation = CABasicAnimation()
animation.keyPath = "transform.rotation"
animation.fromValue = Double.pi / 2
animation.toValue = 2.0
animation.duration = 2
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
b_btn.layer.add(animation, forKey: nil)
}
//位移
func transformTranslationAnimation(){
let animation = CABasicAnimation()
animation.keyPath = "transform.translation.y"
animation.toValue = 100
animation.duration = 2
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
b_btn.layer.add(animation, forKey: nil)
}
//圆角
func transformCornerRadiusAnimation(){
let animation = CABasicAnimation()
animation.keyPath = "cornerRadius"
animation.toValue = 15
animation.duration = 2
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
b_btn.layer.add(animation, forKey: nil)
}
//边框
func transformBorderWidthAnimation(){
let animation = CABasicAnimation()
animation.keyPath = "borderWidth"
animation.toValue = 15
animation.duration = 2
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
b_btn.layer.add(animation, forKey: nil)
}
//颜色渐变
func transformBackgroundColorAnimation(){
let animation = CABasicAnimation()
animation.keyPath = "backgroundColor"
animation.fromValue = UIColor.green.cgColor
animation.toValue = UIColor.red.cgColor
animation.duration = 2
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
b_btn.layer.add(animation, forKey: nil)
}
//淡入淡出
func transformAlphaAnimation(){
let animation = CABasicAnimation()
animation.keyPath = "opacity"
animation.fromValue = 0
animation.toValue = 1.0
animation.duration = 2
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
b_btn.layer.add(animation, forKey: nil)
}
3、总结
位置动画:position、transform.translation.x、transform.translation.y、transform.translation.z
缩放动画:transform.scale.x、transform.scale.y
旋转动画:transform.rotation
颜色动画:backgroundColor、borderColor
淡入淡出动画:opacity
高级效果:圆角动画(cornerRadius)、边框动画(borderWidth)、阴影动画(shadowOffset)