CoreAnimation iOS 动画学习

当然也是站在别人的肩膀上学习,并进行了一些补充

参考:http://www.cocoachina.com/ios/20170124/18617.html

类的继承关系 如下:

一 、基础动画CABasicAnimation

      动画的属性

属性的详细解释

  • repeatCount : 如果在swift中需要一直不断重复:Float.infinity,OC:HUGE_VALF,默认是0,需要手动赋值

  • timingFunction: 主要用来表示动画中的速度变化

    /** Timing function names. **/
@available(iOS 2.0, *)
public let kCAMediaTimingFunctionLinear: String

@available(iOS 2.0, *)
public let kCAMediaTimingFunctionEaseIn: String

@available(iOS 2.0, *)
public let kCAMediaTimingFunctionEaseOut: String

@available(iOS 2.0, *)
public let kCAMediaTimingFunctionEaseInEaseOut: String

@available(iOS 3.0, *)
public let kCAMediaTimingFunctionDefault: String

    

kCAMediaTimingFunctionLinear--在整个动画时间内动画都是以一个相同的速度来改变。也就是匀速运动。一个线性的计时函数,同样也是CAAnimation的timingFunction属性为空时候的默认函数。线性步调对于那些立即加速并且保持匀速到达终点的场景会有意义(例如射出枪膛的子弹)。

kCAMediaTimingFunctionEaseIn:动画开始时会较慢,之后动画会加速。一个慢慢加速然后突然停止的方法。对于之前提到的自由落体的例子来说很适合,或者比如对准一个目标的导弹的发射。

kCAMediaTimingFunctionEaseOut:动画在开始时会较快,之后动画速度减慢。它以一个全速开始,然后慢慢减速停止。它有一个削弱的效果,应用的场景比如一扇门慢慢地关上,而不是砰地一声。

kCAMediaTimingFunctionEaseInEaseOut:动画在开始和结束时速度较慢,中间时间段内速度较快。创建了一个慢慢加速然后再慢慢减速的过程。这是现实世界大多数物体移动的方式,也是大多数动画来说最好的选择。如果只可以用一种缓冲函数的话,那就必须是它了。那么你会疑惑为什么这不是默认的选择,实际上当使用UIView的动画方法时,他的确是默认的,但当创建CAAnimation的时候,就需要手动设置它了。

kCAMediaTimingFunctionDefault:它和kCAMediaTimingFunctionEaseInEaseOut很类似,但是加速和减速的过程都稍微有些慢。它和kCAMediaTimingFunctionEaseInEaseOut的区别很难察觉,可能是苹果觉得它对于隐式动画来说更适合(然后对UIKit就改变了想法,而是使用kCAMediaTimingFunctionEaseInEaseOut作为默认效果),虽然它的名字说是默认的,但还是要记住当创建显式的CAAnimation它并不是默认选项(换句话说,默认的图层行为动画用kCAMediaTimingFunctionDefault作为它们的计时方法)。

x.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)

fillMode : (Defines how the timed object behaves outside its active duration.)主要用来表示动画之外的一些动作

kCAFillModeForwards:动画开始之后layer的状态将保持在动画的最后一帧,而removedOnCompletion的默认属性值是 YES,所以为了使动画结束之后layer保持结束状态,应将removedOnCompletion设置为NO。

kCAFillModeBackwards:将会立即执行动画的第一帧,不论是否设置了 beginTime属性。观察发现,设置该值,刚开始视图不见,还不知道应用在哪里kCAFillModeForwards是在动画开始之后layer迅速进入指定位置开始执行动画并在removedOnCompletion = NO的前提下会停在动画结束的最后位置,而kCAFillModeBackwards则是在动画开始之前迅速进入指定状态并在动画开始后执行动画,动画结束后迅速返回到layer的本身位置

kCAFillModeBoth:该值是 kCAFillModeForwards 和 kCAFillModeBackwards的组合状态

kCAFillModeRemoved:动画将在设置的 beginTime 开始执行(如没有设置beginTime属性,则动画立即执行),动画执行完成后将会layer的改变恢复原状。

尽量不要设置removedOnCompletion = false ,因为配合CAAnimationDelegate会带来循环运用的问题,如果需要动画停留在最后的状态,可以直接设置View的center属性在动画结束的位置Point

之所以会出现 循环引用 因为由于CAAnimation的delegate使用的strong类型:看一下简要的说明图:

speed : 动画的速度,默认一倍速度,会影响duration的值。

timeoffset: 设置动画的时间容错

byValue: 主要是设置动动画开始到这个值的动画,当把fromValue 和 toValue 设置成0 就可以看到这个属性值的效果了

removedOnCompletion = false 可以避免跳转下一页面返回后动画停止

 KeyPath值:(andriod 动画也是类似的实现方式)

let rotationAnim = CABasicAnimation.init(keyPath: "transform.rotation.x")

看到这里的keyPath,我觉得应该就想到oc 中的kvc 了,那么就应该跟属性值有关系

在写动画的时候,只有把动画加到layer对象上去,才可以实现

 rotationViewX.layer.add(rotationAnim, forKey: "rotationAnimX")

所以这里的属性值应该就是CALayer 的属性值了,这里的key 不能省略,否则动画无法实现,我觉得应该是为了标记动画为动画组的实现准备的

一个 CABasicAniamtion 的实例对象只是一个数据模型,和他绑定到哪一个layer上是没有关系的

方法addAnimation:forKey:是将 CABasicAniamtion 对象进行了 copy 操作的。所以在将其添加到一个layer上之后,我们还是将其再次添加到另一个layer上的。

二、关键帧动画 CAKeyframeAnimation

values: 需要指明整个动画过程中的关键帧点,并且起点必须为数组的第一个值,让动画沿着关键帧点进行运动

path 属性:指定的是一个路径,整个动画将根据这个路径进行运动。可以看出,其和values 作用相同,正因为此,两者互斥,当values 和path 同时指定时,path 会覆盖values,即values 的属性将被忽略。

keyTimes属性:如果你没有显式地对keyTimes进行设置,则系统会默认每条子路径的时间 为:ti=duration/(5-1),即每条子路径的duration相等,都为duration的1\4。当然,我们也可以传个数组让物体快慢结 合。例如,你可以传入{0.0, 0.1,0.6,0.7,1.0},其中首尾必须分别是0和1,因此tAB=0.1-0, tCB=0.6-0.1, tDC=0.7-0.6, tED=1-0.7.....一个包含若干NSNumber对象值的数组,用来区分动画的分割时机。值得注意的是,这些NSNumber对象的浮点型值在0.0~1.0之间。里面的值后一个比前一个要大或者相等。最好的结果是这个数组中的值和values里面的值或者path控制的值对应,否则可能会出现不了你想要的结果。属性为应用在每一关键帧指定应用到每一个关键帧上的计时器。该属性只在calculationMode属性被设置为kCAAnimationLinear,kCAAnimaitonDiscrete,kCAAnimationCubic时被使用。它不使用在节奏动画中。keyTimes定义了应用在每一关键帧的时间点。所有中间值的定时由定时函数控制,定时函数允许你对各个部分应用缓入或缓出曲线定时。如果你不指定任何定时函数,动画将会是线性的

caculationMode:在关键帧动画中还有一个非常重要的参数,那便是calculationMode,计算模式.其主要针对的是每一帧的内容为一个座标点的情况,也就是对anchorPoint 和 position 进行的动画.当在平面座标系中有多个离散的点的时候,可以是离散的,也可以直线相连后进行插值计算,也可以使用圆滑的曲线将他们相连后进行插值计算.该属性决定了物体在每个子路径下是跳着走还是匀速走,跟timeFunctions属性有点类似

1)kCAAnimationLinear calculationMode的默认值,r自定义控制动画的时间(线性)可以设置keyTimes,表示当关键帧为座标点的时候,关键帧之间直接直线相连进行插值计算;

2)kCAAnimationDiscrete 离散的,就是不进行插值计算,所有关键帧直接逐个进行显示;

3)kCAAnimationPaced 节奏动画自动计算动画的运动时间,使得动画均匀进行,而不是按keyTimes设置的或者按关键帧平分时间,此时keyTimes和timingFunctions无效;

4)kCAAnimationCubic 对关键帧为座标点的关键帧进行圆滑曲线相连后插值计算,对于曲线的形状还可以通过tensionValues,continuityValues,biasValues来进行调整自定义,这里的数学原理是Kochanek–Bartels spline,这里的主要目的是使得运行的轨迹变得圆滑,曲线动画需要设置timingFunctions

kCAAnimationCubicPaced 看这个名字就知道和kCAAnimationCubic有一定联系,其实就是在kCAAnimationCubic的基础上使得动画运行变得均匀,就是系统时间内运动的距离相同,此时keyTimes以及timingFunctions也是无效的.

测试demo:

1、一个方形的运行轨迹,使用values

 func initRectLayer() {
        
        rectLayer = CALayer.init()
        rectLayer?.frame = CGRect.init(x: 15, y: 200, width: 30, height: 30)
        rectLayer?.cornerRadius = 15
        rectLayer?.backgroundColor = UIColor.black.cgColor
        view.layer.addSublayer(rectLayer!)

        let rectRunAm = CAKeyframeAnimation.init(keyPath: "position")
        
        //设置关键帧的位置,必须包含起始位置
        rectRunAm.values = [NSValue.init(cgPoint: (rectLayer?.frame.origin)!),NSValue.init(cgPoint: CGPoint.init(x: 320 - 15, y: (rectLayer?.frame.origin.y)!)),NSValue.init(cgPoint: CGPoint.init(x: 320 - 15, y: (rectLayer?.frame.origin.y)! + 100)),NSValue.init(cgPoint: CGPoint.init(x: 15, y: (rectLayer?.frame.origin.y)! + 100)),NSValue.init(cgPoint: (rectLayer?.frame.origin)!)]
       //设定每个关键帧的时长,如果没有显示的设置,则默认总时长/(value.count-1)
        rectRunAm.keyTimes = [0.0,0.6,0.7,0.8,1]
        
rectRunAm.timingFunctions=[CAMediaTimingFunction.init(name: kCAMediaTimingFunctionEaseOut),CAMediaTimingFunction.init(name: kCAMediaTimingFunctionEaseIn),CAMediaTimingFunction.init(name: kCAMediaTimingFunctionLinear),CAMediaTimingFunction.init(name: kCAMediaTimingFunctionLinear)]
        
        rectRunAm.repeatCount = 1000
        
        rectRunAm.autoreverses = false
        
        rectRunAm.calculationMode = kCAFilterLinear
        
        rectRunAm.duration = 4
        
        rectLayer?.add(rectRunAm, forKey: "rectRunAnimation")
    }
    
    //动画暂停
    func pauseLayer(_ layer: CALayer) {
        
        let pauseTime = layer.convertTime(CACurrentMediaTime(), from: nil)
        
        layer.speed = 0.0
        
        layer.timeOffset = pauseTime
    }
    
    //动画恢复
    func resumLayer(_ layer: CALayer) {
        
        let pauseTime = layer.timeOffset
        
        layer.speed = 1.0
        
        layer.timeOffset = 0
        
        layer.beginTime = 0
        
        let timeSincePause = layer.convertTime(CACurrentMediaTime(), from: nil) - pauseTime
        
        layer.beginTime = timeSincePause
    }

 2、使用路径

 func cornerAnimation() {
        
        //初始化试图对象
        let bgView = UIView.init(frame: CGRect.init(x: 50, y: 100, width: 250, height: 500))
        
        let bezierPath = UIBezierPath.init(ovalIn: bgView.frame)
        
        let animView = UIView.init(frame: CGRect.init(x: 50, y: 50, width: 50, height: 50))
        animView.backgroundColor = UIColor.blue
        
        view.addSubview(animView)
        
        //绕行的动画
        let orbitAnim = CAKeyframeAnimation.init(keyPath: "position")
        
        orbitAnim.duration = 5
        
        orbitAnim.path = bezierPath.cgPath
        
        orbitAnim.calculationMode = kCAAnimationPaced
        
        orbitAnim.fillMode = kCAFillModeForwards
        
        orbitAnim.repeatCount = Float.infinity
        
        orbitAnim.rotationMode = kCAAnimationRotateAutoReverse
        
        animView.layer.add(orbitAnim, forKey: "orbitAnim")
        
        //画运动轨迹
        let shapLayer = CAShapeLayer()
        shapLayer.strokeColor = UIColor.purple.cgColor
        shapLayer.fillColor = UIColor.clear.cgColor
        shapLayer.lineWidth = 0.5
        shapLayer.lineJoin = kCALineJoinRound
        shapLayer.lineCap = kCALineCapRound
        shapLayer.path = bezierPath.cgPath
        view.layer.addSublayer(shapLayer)
    }
rotationMode:旋转样式

kCAAnimationRotateAuto 根据路径自动旋转

kCAAnimationRotateAutoReverse 根据路径自动旋转

三、转场动画 CATransition


主要用于转场动画从一个场景以动画的形式过渡到另一个场景

1.属性解释

type:转场动画的类型,一个自定义的转场动画中指定的过滤器属性

另外还有一些系统未公开的动画效果:


["cube", "suckEffect", "rippleEffect", "pageCurl", "pageUnCurl", "oglFlip", "cameraIrisHollowOpen",  "cameraIrisHollowClose", "spewEffect","genieEffect","unGenieEffect","twist","tubey","swirl","charminUltra", "zoomyIn", "zoomyOut", "oglApplicationSuspend"]
效果,就不一一列举了,可以看下效果图

subtype:转场动画将要去往的方向
startProgress、endProgress: 开始和结束的位置进度,数值介于[0,1]之间,结束值一定是大于开始值的

四、CASpringAnimation

iOS9才引入的动画类,在以前我们都是使用facebook的pop来做这种弹簧效果,它继承于CABaseAnimation,用于制作弹簧动画

1.参数说明

mass:质量,影响图层运动时的弹簧惯性,质量越大,弹簧拉伸和压缩的幅度越大,动画的速度变慢,并且波动幅度变大
stiffness:刚度系数(劲度系数/弹性系数),刚度系数越大,形变产生的力就越大,运动越快
damping:阻尼系数,阻止弹簧伸缩的系数,阻尼系数越大,停止越快
initialVelocity:初始速率,动画视图的初始速度大小速率为正数时,速度方向与运动方向一致,速率为负数时,速度方向与运动方向相反如果
settlingDuration:结算时间 返回弹簧动画到停止时的估算时间,根据当前的动画参数估算通常弹簧动画的时间使用结算时间比较准确








  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值