关键帧动画,也是CAPropertyAnimation的子类,与CABasicAnimation的区别是:CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue),而CAKeyframeAnimation会使用一个NSArray保存这些数值。CABasicAnimation可看做是只有2个关键帧的CAKeyframeAnimation。
values:是关键帧动画最重要的一部分,该值定义了动画执行的行为,它是一个数组,里面的元素理解为”关键帧”(keyframe)。动画对象会在指定的时间(duration)内,依次显示values数组中的每一关键帧。在添加到数组之前,需要注意:有些对象可以直接添加到数组当中,但是有些对象必须在被添加之前需要进行包装,比如:有些对象需要包装为id类型,而标量数据类型或者结构体必须被包装成为对象,例如:
1:如果属性是 CGRect类型(比如: bounds and frame 属性),应该包装每一个矩形成为NSValue对象。
2:对于layer的transform属性,需要包装每一个值CATransform3D成为NSValue对象。
3:对于borderColor属性,在被添加到数组之前,需要把CGColorRef数据类型包装成为id类型。
4:对于CGFloat值,包装为NSNumber对象。
5:对于layer的contents属性,使用CGImageRef属性类型。
6:对于CGPoint数据类型,可以使用NSValue对象进行包装,也可以使用CGPathRef对象使用路径进行包装。
path:这是一个可选的路径对象,默认是nil.它定义了动画的行为,当path的值非nil时,将覆盖values属性的值,作用与values属性一样(即:如果你设置了path,那么values将被忽略。)对于常速路径动画, calculationMode应该被设置为 paced。我们可以设置一个CGPathRef\CGMutablePathRef,让层按照这个路径进行动画移动。
keyTimes:这是一个可选的轨迹动画的时间数组,数组中的每一个值都是NSNumber对象,并且取值范围在 [0,1]。它定义了动画的步调,数组中的每一个值都与 values中的值一一对应(可以理解为对应的关键帧指定对应的时间点,keyTimes中的每一个时间值都对应values中的每一帧.)。所提每个帧显示的周期为keyTimes*duration。
timingFunctions:这是一个可选数组,数组中的值是CAMediaTimingFunction类型,如果 values数组定义了n关键帧,那么该数组就需要 n-1个CAMediaTimingFunction值。每一个CAMediaTimingFunction值描述了关键帧从一个值到另一个值之间过渡的步调(即:运动的时间函数)。
kCAMediaTimingFunctionLinear(线性):匀速,给你一个相对静态的感觉
kCAMediaTimingFunctionEaseIn(渐进):动画缓慢进入,然后加速离开
kCAMediaTimingFunctionEaseOut(渐出):动画全速进入,然后减速的到达目的地
kCAMediaTimingFunctionEaseInEaseOut(渐进渐出):动画缓慢的进入,中间加速,然后减速的到达目的地。
kCAMediaTimingFunctionDefault (默认时间函数)
应用:
//淡出动画效果
func transformAlphaAnimation(){
let animation = CAKeyframeAnimation()
animation.keyPath = "opacity"
animation.values = [0.9,0.8,0.3,0.0]
animation.duration = 5
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
b_btn.layer.add(animation, forKey: nil)
}
//任意路径动画
func positionAnimation(){
let animation = CAKeyframeAnimation()
animation.keyPath = "position"
let pathLine = CGMutablePath()
pathLine.move(to: CGPoint(x: 10, y: 10))
//直线
// pathLine.addLine(to: CGPoint(x: 100, y: 100))
//圆弧
pathLine.addArc(center: CGPoint(x: 100, y: 100), radius: 100, startAngle: 0, endAngle: CGFloat(Double.pi/2), clockwise: true)
animation.path = pathLine
animation.duration = 5
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
b_btn.layer.add(animation, forKey: nil)
}
//组合动画
func groupAnimation(){
let move = CABasicAnimation()
move.keyPath = "position"
move.toValue = CGPoint(x: b_btn.x - 10, y: b_btn.y - 10)
let scale = CABasicAnimation()
scale.keyPath = "transform.scale.x"
scale.fromValue = 1.0
scale.toValue = 0.8
let ransform = CABasicAnimation()
ransform.keyPath = "transform.rotation"
ransform.fromValue = Double.pi / 2
ransform.toValue = 2.0
let animationGroup = CAAnimationGroup()
animationGroup.animations = [move,scale,ransform]
animationGroup.duration = 5
animationGroup.fillMode = kCAFillModeForwards
animationGroup.isRemovedOnCompletion = false
b_btn.layer.add(animationGroup, forKey: nil)
}